IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

2D Java Discussion :

Optimisation du rafraichissement d'un viewer de courbe


Sujet :

2D Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut Optimisation du rafraichissement d'un viewer de courbe
    Bonjour à tous,

    J'ai développé un viewer de courbes XY.

    Pour afficher une courbe, un algo permet de réduire le nombre de point à afficher pour ne pas faire planter la carte graphique.
    (les courbes peuvent avoir plusieurs dizaines de million de points...).

    Cet algo peut prendre un peu de temps pour calculer la courbe à afficher.

    Deux soucis se posent :
    1) Comment éviter de figer l'affichage du fait que l'algo est lancé dans la méthode "paintComponent(Graphics g)" du JComponent par définition?

    2) Est il possible de gérer des demandes de rafraichissement multiples?
    Genre si un rafraichissement est en cours mais qu'une nouvelle demande arrive on "tue" le précèdent rafraichissement pour ne réaliser que le dernier demandé.

    J'ai tenté ceci mais les courbes ne s'affiche plus (réalisé dans la méthode: view.draw(...)):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    /*
     * (non-Javadoc)
     * @see math.xyploter.data.view.CurvesView#draw(java.awt.Graphics2D, java.awt.geom.Rectangle2D, math.xyploter.axis.Axis, math.xyploter.axis.Axis, math.number.ValueReader)
     */
    @Override
    public void draw(final Graphics2D g2, final Rectangle2D parentBounds, final Axis xAxis, final Axis yAxis, final ValueReader reader) {
    	try {
    		if (drawThread != null && drawThread.isAlive()) {
    			drawThread.interrupt();
    			drawThread.join();	// wait before continue
    		}
     
    		Runnable r = new Runnable() {
    			public void run() {
    				for (V view:MainCurveViews.this) {
    					if (Thread.currentThread().isInterrupted()) {
    						break;
    					}
    					view.draw(g2, parentBounds, xAxis, yAxis, reader);
    				}
    			};
    		};
     
    		drawThread = new Thread(r);
    		drawThread.setDaemon(true); 	// allows not stopping the JVM close method
    		//drawThread.setPriority(Thread.MIN_PRIORITY);
    		drawThread.start();
    	}
    	catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
    	catch(java.util.ConcurrentModificationException e) {
    		System.out.println("MainCurveViews.draw() error:ConcurrentModificationException");
    	}
    }
    D'avance merci pour votre aide.

  2. #2
    Membre averti
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mai 2020
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte technique

    Informations forums :
    Inscription : Mai 2020
    Messages : 325
    Points : 436
    Points
    436
    Par défaut
    Bonjour,

    Swing gère déjà des threads pour séparer la présentation du reste de l'application. Ça me paraît assez étrange de lancer un thread dans les méthodes dessin.

    Peut-être pourriez vous utiliser un SwingWorker pour calculer les points en arrière-plan et mettre à jour quand le calcul est terminé. Vous pourriez même faire des mises à jour au fur et à mesure du calcul.

    https://docs.oracle.com/javase/7/doc...ingWorker.html

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Bonjour et merci pour ta réponse,

    J'ai tenté d'utiliser un SwingWorker. Mais les courbes ne s'affichent toujours pas.

    Un peu de précision sur ma structure de classe :
    - une classe MainView possède une liste de ViewCurve de courbe.
    La méthode draw ci dessus appartient à cette classe MainView.
    Elle est lancée par la méthode "paintComponent(Graphics g)" du JComponent qui contient le ploter (contenant le MainView).
    C'est pour cela que je lance les viewCurve.draw(...) dans un thread pour les détacher de l'EDT.

    - la classe ViewCurve dispose d'un renderer pour afficher la courbe sur l'écran. La methode ViewCurve.draw(...) est définit ci-dessous.
    Elle lance simplement la méthode draw() du renderer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    	/* (non-Javadoc)
    	 * @see com.math.xyploter.data.view.ICurveView#draw(java.awt.Graphics2D, java.awt.geom.Rectangle2D, com.math.xyploter.axis.Axis, com.math.xyploter.axis.Axis, com.math.number.ValueReader)
    	 */
    	@Override
    	public void draw(Graphics2D g2, Rectangle2D parentBounds, Axis xAxis, Axis yAxis, ValueReader reader) {
    		this.getRenderer().draw(g2, parentBounds, xAxis, yAxis, reader);
    	}
    Voici ce qui j'ai fait avec le SwingWorker:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    public class XYLineRendererWorker extends SwingWorker<Boolean, XYLine> {
     
    	public XYLineRenderer renderer;
    	public Graphics2D g2;
    	public Rectangle2D parentBounds;
    	public Axis xAxis;
    	public Axis yAxis;
    	public ValueReader reader;
     
    	public XYLineRendererWorked(XYLineRenderer renderer, Graphics2D g2, Rectangle2D parentBounds, Axis xAxis, Axis yAxis, ValueReader reader) {
    		this.renderer = renderer;
    		this.g2 = g2;
    		this.parentBounds = parentBounds;
    		this.xAxis = xAxis;
    		this.yAxis = yAxis;
    		this.reader = reader;
    	}
     
     
    	/* (non-Javadoc)
    	 * @see javax.swing.SwingWorker#doInBackground()
    	 */
    	@Override
    	protected Boolean doInBackground() throws Exception {
    		//construction des points de la courbe "affichable"...
     
    		return true;
    	}
     
    	@Override
    	protected void process(List<XYLine> lines) {
    		for (XYLine l: lines)
    			g2.drawLine(l.x1, l.y1, l.x2, l.y2);
    	}
    }
    Pour faire simple la méthode "doInBackground()" est un copié collé de la methode viewCurve.draw(...) dans lequel les
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g2.drawLine(x1, y1, x2, y2);
    ont été remplacés par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    publish(new XYLine(x1, y1, x2, y2));
    La méthode CurveRenderer.draw(...) est définie ci-dessous.
    Elle construit et lance le worker.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    	/*
    	 * (non-Javadoc)
    	 * @see math.xyploter.data.renderer.CurveRenderer#draw(java.awt.Graphics2D, java.awt.geom.Rectangle2D, math.xyploter.axis.Axis, math.xyploter.axis.Axis, math.number.ValueReader)
    	 */
    	@Override
    	public void draw(Graphics2D g2, Rectangle2D parentBounds, Axis xAxis, Axis yAxis, ValueReader reader) {
    		if ((parentBounds.getHeight()<20) || parentBounds.getHeight()<20)
    			return;
     
    		initPaint(g2);
     
    		XYLineRendererWorker worker = new XYLineRendererWorker(this, g2, parentBounds, xAxis, yAxis, reader);
    		worker.execute();
    	}
    Il me semble que le détachement de EDT est réalisé par le thread dans le draw(...) de la MainView.
    Et que la synchro avec l'EDT est réalisée avec le worker.
    Avec vous une idée sur ce qui cloche?

  4. #4
    Membre averti
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mai 2020
    Messages
    325
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte technique

    Informations forums :
    Inscription : Mai 2020
    Messages : 325
    Points : 436
    Points
    436
    Par défaut
    ...La méthode draw .. est lancée par la méthode "paintComponent(Graphics g)"... C'est pour cela que je lance les viewCurve.draw(...) dans un thread pour les détacher de l'EDT.
    J'ai l'impression que c'est la tout votre problème. Swing et le SwingWorker vont se charger de processer les résultats dans le bon thread d'affichage. Il faudrait lancer le worker en dehors du draw qui est déjà dans le cycle de "dessin".

    Par exemple, lorsque un point est rajouté, vous lancez le worker qui va faire son calcul en arrière-plan et délivrer des valeurs au fur et à mesure. Ça n'est qu'à la réception de ces valeurs que vous redessinez le composant sans utiliser de thread, car le worker s'en charge déjà pour vous.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Je suis d'accord avec le fait que le traitement est lancé initialement par l'EDT à travers la méthode "paintComponent(Graphics g)".

    L'objet Curve n'est pas lié à la partie graphique (c'est une volonté). Il peut être créé et modifié indifféremment du graphique.
    C'est pour cela que j'ai une classe ViewCurve. Cette classe rend une curve "dessinable". Elle gère les modifications de curve et son dessin (en fonction des propriétés du view) dans le ploter.
    Il est donc normal que ce soit le graphique qui demande à se rafraichir (à travers la méthod "paintComponent(Graphics g)").

    J'ai lancé un thread pour le détacher de l'EDT.
    Il me semble que c'est l'objectif du thread. Je me trompe?

    J'ai fait un "SwingUtilities.isEventDispatchThread()" dans le thread créé dans le MainView.draw() (dans le runnable.run() du premier message). Il me retourne bien false.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Je pense avoir trouvé pourquoi les courbes ne s'affiche pas.

    Ci-dessous la méthode paintComponent().

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    /*
     * (non-Javadoc)
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    @Override
    public void paintComponent(Graphics g) {
    	super.paintComponent(g);
    	Graphics2D g2 = (Graphics2D) g.create(0, 0, getWidth(), getHeight());
    	//...
     
    	desk.draw(g2, bounds);
     
    	//g2.dispose();
    	System.out.println("Stop DrawablePanel.paintComponent()");	
    }
    desk est un object de type Drawable (qui possède une liste d'objet de type Drawable...)
    En partant de cette méthode paintComponent, voici la succession d'appel des méthodes paint() et draw() des différents objects.
    Désolé pour la forme synthétique. J'espère que cela se comprend.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    DrawablePanel.paintComponent(){
    	for (Drawable drawable:drawables)
    		drawable.paint();
    }
     
    XYPlot extends Drawable;
     
    XYPlot.paint(){
    	(XYPlotRenderer) getXYPlotRenderer().paint() {
    		// dessine la grille et les axes
     
    		(MainCurvesView) getMainCurvesView().draw(){
    			for (CurveView view:getCurveViews())
    				view.getRenderer().draw(){		// La méthode CurveRenderer.draw(...) est définie dans mon précedent message (création du SwingWorker()
    					//...
    					XYLineRendererWorker worker = new XYLineRendererWorker(this, g2, parentBounds, xAxis, yAxis, reader);
    					System.out.println("Start SwingWorker");
    					worker.execute();
    			}
    		}
    		// ...
    	}
    }
    Donc si vous avez tout suivi, le soucis vient du fait que lors de la création du swingworker, on "libère" la méthode view.getRenderer().draw().
    Elle peut se terminer pour revenir à la fin de l'exécution de la méthode paintComponent() (après la fin de l'appel de la ligne desk.draw(g2, bounds).
    On exécute donc "g2.dispose();" !!!

    Alors que l'EDT n'a peut être pas encore débuté l'affichage des courbes.
    Je dis peut "être pas" mais c'est sur, du fait du long temps de calcul d'affichage de ces courbes.

    J'ai le problème mais pas la solution propre pour bien structurer mon code. avez vous des suggestions?

  7. #7
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Je reviens pour expliquer un peu plus en détails ce qui a déjà été mentionné :

    L'EDT (Event Dispatch Thread) est le thread évènementiel de AWT et Swing. Il gère entre autres, la propagation des événements et le rendu de l'interface graphique, partant de l’hypothèse que tous ces traitements sont rapides avec un temps d’exécution petit ou négligeable. Le thread passe donc son temps a alterner entre ces deux états : propagation, rendu, propagation, rendu, etc.

    Donc, forcement, tout traitement long (connexion a une BD, une URL distante, lecture d'un gros fichier, gros traitement) effectué en réponse a un événement, s’insère entre 2 phases de rafraîchissement de l’interface ( -> syndrome seul le résultat final s'affiche, on voit aucune étape intermédiaire) et de facto "bloque" complètement l'EDT tant que le traitement est en cours ce qui a tendance a donner a l'utilisateur l’impression que le programme est planté ( -> plus rien répond quand on clique dans la GUI).

    Il faut donc déporter les traitements longs dans des threads annexes, par exemple, en utilisant les framework qui sont fournis tels que SwingWorker. Non seulement le traitement peut s'effectuer sans monopoliser l'EDT, mais cela permet aussi de faire des mises a jour partielles de l'interface graphique (ce qui est bien du point de vue de l'utilisateur car ça lui donne l’idée que le programme "est en train de faire quelque chose").

    A noter que l'EDT peut aussi être monopolisé par un rendu complexe qui est lui aussi une sorte de traitement long. Pour éviter ce soucis, il existe pas mal de méthodes avancées de rendu 2D tels que l'utilisation des dirty areas (on appelle repaint() en spécifiant la boite englobante de la zone sale) et zone de clips pour réduire la zone a redessiner ou carrément en faisant un rendu dans une image offscreen via un thread séparé, image qui sera ensuite composée a l’écran.

    Ce concept s'applique également a l'identique avec JavaFX et son Dispatch Thread.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Bonjour bouye et merci pour ce complément sur l'EDT.

    Il me semble avoir compris le concept de l'EDT après mes nombreuses recherches.
    Ce que je ne comprend pas c'est pourquoi dès que je place mon code de dessin de la courbe dans un swingworker il ne s'affiche plus.

    Je résume mon programme:
    - L'EDT va demandé le rafraichissement du DrawablePanel par la méthode paintComponent(Graphics g) [on est donc dans l'EDT]
    - le DrawablePanel va demander à tous ses fils de type Drawable de se rafraichir en appelant la méthode Drawable.paint()
    - pour se dessiner les Drawable appellent la méthode draw() de leur renderer. [on est toujours dans l'EDT]

    C'est ici que l'on a un traitement long.
    On crée donc un SwingWorker dans le curve.getRenderer().draw() pour "libérer" l'EDT.
    Le SwingWorker fera des demandes à l'EDT "proprement" par la suite pour afficher le composant.

    Voici le code du SwingWorker:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    public class XYLineRendererWorker extends SwingWorker<Boolean, XYLine> {
     
    	public XYLineRenderer renderer;
    	public Graphics2D g2;
    	public Rectangle2D parentBounds;
    	public Axis xAxis;
    	public Axis yAxis;
    	public ValueReader reader;
     
    	public XYLineRendererWorker(XYLineRenderer renderer, Graphics2D g2, Rectangle2D parentBounds, Axis xAxis, Axis yAxis, ValueReader reader) {
    		this.renderer = renderer;
    		this.g2 = g2;
    		this.parentBounds = parentBounds;
    		this.xAxis = xAxis;
    		this.yAxis = yAxis;
    		this.reader = reader;
    	}
     
    	/* (non-Javadoc)
    	 * @see javax.swing.SwingWorker#doInBackground()
    	 */
    	@Override
    	protected Boolean doInBackground() throws Exception {
    		XYCurveView view = ((XYCurveView) renderer.getView());
    		XYCurveDouble curve = view.getCurve(reader);
     
    		if (view.isVisible().isTrue() && (curve.getCount()>0)){
    			//... calcul de la courbe à afficher
    		}
    		System.out.println("is finish.");
    		return true;
    	}
     
    	@Override
    	protected void process(List<XYLine> lines) {
    		int lastShapePtX = -Integer.MAX_VALUE;
     
    		renderer.initPaint(g2);
     
    		if (!lines.isEmpty()) {
    			XYLine line = lines.get(0);
    			lastShapePtX = drawShape(g2, lastShapePtX, line.x1, line.y1);
     
    			for (XYLine l: lines) {
    				if (Thread.currentThread().isInterrupted()) {
    					System.out.println("SW is interrupted.");
    					break;
    				}
    				g2.drawLine(l.x1, l.y1, l.x2, l.y2);
    				lastShapePtX = drawShape(g2, lastShapePtX, l.x2, l.y2);
    			}
    		}
    	}
     
    	private int drawShape(Graphics2D g2, int lastX, int x, int y){
    		...
    	}
     
    	/*
    	 * (non-Javadoc)
    	 * @see javax.swing.SwingWorker#done()
    	 */
    	@Override
    	public void done() {
    		System.out.println("is done.");
    	}
    }
    Les println montrent que le SwingWorker semble se lancer correctement.
    Voici la console:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Start DrawablePanel.paintComponent()
    Start SwingWorker
    Stop DrawablePanel.paintComponent()
    is finish.
    is done.
    une idée du pourquoi je ne vois pas les courbes s'afficher?

  9. #9
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Alors je peux pas trop tester vu qu'on a pas l'intégralité du code dans un exemple autosuffisant, mais le squelette de ton worker semble en effet assez étrange : pour ce que j'en ai compris (et je peux m'être gourré), tu sembles manipuler un graphics et dessiner dedans en plus de faire la simplification des points dont tu parlais. Or si ce graphics provenant d'une image offscreen pourquoi pas ; mais non il semble que ça soit le graphics associé à l'écran. Or ça c'est MAL ! Sauf cas particuliers, quand le programmeur sait vraiment ce qu'il veut faire, le dessin à l'écran doit se faire durant l'EDT !

    EDIT - relecture, process() est censé se dérouler durant l'EDT, il me semble (ça fait un bail que j'ai pas fait du Swing à plein temps). Mais ça ne peux pas sauver le bousin car tu as aucune idée de l'état du graphics associé à l'écran à ce moment là. En effet, celui-ci est constamment nettoyé et réutilisé, son clip, l'origine de son repère, ses transformations, tous ses états modifiés, pour les besoin de la GUI pour dessiner des trucs aux 4 coins de l'écran. Bref, c'est tout le concept de vouloir conserver une référence dessus qui est foiré. Ton but est de demander à ton composant qui est chargé d'afficher les courbes à l'écran de se rafraichir via un repaint() et de lui signaler quelles courbes ont changé si tu veux faire quelques optimisations ; c'est lui qui fera le dessin quand le moment sera venu (quand son paintComponent() est invoqué par le repaint manager). Ce n'est pas à toi de dessiner activement à l'écran, tout le principe de AWT/Swing repose sur un dessin passif. Laisse ton worker se charger de la simplification des points c'est son boulot.

    Si tu veux vraiment faire du rendu actif, il faut passer par une image offscreen ou des trucs plus avancés comme des buffer strategy.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

Discussions similaires

  1. [XL-2010] Optimiser le rafraichissement d'une user form
    Par andy.spit dans le forum Macros et VBA Excel
    Réponses: 15
    Dernier message: 11/12/2012, 10h53
  2. Réponses: 1
    Dernier message: 06/06/2010, 10h33
  3. Fittage d'un courbe (optimisation)
    Par Bouchaa dans le forum MATLAB
    Réponses: 1
    Dernier message: 18/05/2010, 22h57
  4. optimiser le tracé d'une courbe
    Par Zorgz dans le forum 2D
    Réponses: 3
    Dernier message: 04/09/2006, 16h17
  5. [TP]Optimiser le rafraîchissement de l'écran en mode texte?
    Par Ponytear dans le forum Turbo Pascal
    Réponses: 8
    Dernier message: 15/02/2004, 11h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo