Partage

dessiner en java

demi disque et courbe

Le 28 mai 2009 à 15:34:25

Bonjours a tous

pour la premiere fois, je doit dessiner en java......

bon, j'ai vue qu'il falait utiliser la class Graphics mais, je ne sais pas trop comment dessiner ce que je veux....

je fournie une valeur toutes les 50ms et je voudrai que cela soit représenté par :
Image utilisateur
et
Image utilisateur

la valeur en haut est la valeur que je peux fournir.

merci pour votre aide ;)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Publicité
Le 28 mai 2009 à 15:34:25
Le 28 mai 2009 à 15:48:22

Rien compris.
C'est quoi les valeurs que tu as mises ?
J'espère que t'as des notions en maths pour tracer les graphes.
Pour la première le plus simple serait d'avoir la fonction associée.
Comme ça m'étonnerait que tu l'aies, va falloir imaginer un système d'axes et de tracer les points (puis les relier).
Quant au "demi-disque" ça me semble déjà plus aisé.
Tu peux par exemple tracer le demi-disque d'une couleur puis le recouvrir avec la couleur de l'arrière plan selon l'angle que tu souhaites.
Y'a aussi le GeneralPath sinon mais tu vas galérer avec si t'y connais rien ^^'
Le 28 mai 2009 à 15:58:32

en faite, j'ai un .class (je n'ai pas le source) que me fournit un aléatoirement une serie de chiffre....(aléatoirement ou non)

et avec cela, il faut que je trace ces deux types de graphe.....

edit: j'ai essayé d'utiliser la methode drawPolyline(int x [],int y[],nbpoint);
donc, j'ai remplie un tableau x de 100 case, de 0 a 99
et un tableau y avec les valeur que je peux utiliser (retourné par mon .class)
donc voici ce que j'ai fait:

private int [] x=new int [100];
private int [] y=new int[100];


puis dans une methode qui est apeller toutes les 50ms

int j=0;
if(j>=99)
{
	j=0;
}
else
{
	j++;
	y[j]=valCour2; //valCour2 est la valeur que je recuperer toutes les 50ms
	x[j]=j;
}


puis j'ai fait:
drawPolyline(x, y, 100);


et la,j'ai un graph qui est crée, mais, il ne bouge que sur y, pas sur x.
donc, je ne voit qu'un trait qui monte et qui descend.....

il faudrai que ça continu a monté et descendre, mais aussi que cela ce deplace selon l'axe x et aussi que cela soit centré dans la fentre...

help me please

edit:
j'ai mit une video de l'execution pour vous donnez une idée du probleme....

edit2:
bon, j'ai presque réussi a faire le disque......
la bouge bien et tout, mais, mes valeur varie entre 0 et 100
donc, je voudrai que sur le graph sa part de 0 jusqu'a 180
enfin, sa je vais trouver ;)

voici un petit screen
Image utilisateur
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 16:58:46

Un truc plus simple
- Tu defini ton mini repère (plan)
- tu fais une boucle qui lit les valeurs
- Pour chaque valeur (correspondant à l'ordonnée ) tu trace une ligne -->
public paint(Graphics g)
{
int old_x=0;
int old_y=0;
float echelle= 1/100;
while(valeur=getvaleur())
 {
   new_y=getValeur()*echelle;
   g.drawLine(old_x,old_y,old_x+10,new_y);
   old_x+=10;
   old_y=new_y;
   Thread.sleep(50);
 }
}


Voila comment je peux résumé ma pensée. Mais je n'ai pas testé le code il peux y avoir des erreur de syntaxes
J'ai tous les badges d'OpenClassrooms.
Le 28 mai 2009 à 18:48:25

Ta méthode que tu appelles toutes les 50ms elle réinitialise j à 0 à chaque fois. Y'a pas comme une erreur là ?
Tout dépend de ta méthode complète mais si tu remets j à 0 à chaque fois aucun risque qu'elle dépasse 1.
drawPolyline marche aussi, y'a juste à récupérer les coordonnées de chaque point dans le repère... j'imagine que (Ox) est l'axe des temps et (Oy) la valeur mesurée. Y'a juste à ajuster les échelles et c'est bon.
C'est essentiellement des maths ton soucis je pense.
Le 28 mai 2009 à 19:51:32

ma methode resort les valeur de deux façon:
soit aleatoirement entre 0 et 99 ou de maniere "sinusoidale"
(0,1,2,3,....99,98,97,...0,1,2......)

je regarde tous cela ;)

bon, j'ai résolu le probleme pour le demi disque, il tourne sans probleme ;)

sinon, j'ai fait une petite video pour vous montré l'execution du programme.....
(effectivement je remettait j a zero a toute les 50ms...... :-° )

la video sur youtube

vous aller voir sur la video, ce que je voudrai, c'est placer le graph plus bas, et reduire l'echelle (afin qu'il n'arrive jamais a la même auteur que l'affichage des nombre ;))

aussi, il faudrai qu'il ce dessine a partir de la gauche et "pousse" le reste du graph au fur et a mesure..... (la, il ce dessine depuis le bout du graph et donc ne ce "pousse" pas...)
comme ceci:
Image utilisateur

voila, a part cela, j'ai un autre probleme, mais que je pense resoudre de moi même, merci encore pour votre aide ;)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 20:23:18

Pour que le graphe se pousse il suffit de faire subir une translation à tous tes points.
Sur ton graphe y'a un petit truc c'est que le premier point est toujours relié : il me semble que c'est dû au fait que dans drawPolyline tu mettes 100 au lieu de 99 (à vérifier).
Pour déplacer l'origine de l'axe, comme je crois que tu prends le repère que te donne Java, il va falloir faire subir une ou deux translations à ton axe.
Le 28 mai 2009 à 20:31:49

Utilise AffineTransform, et tu fait une translation sur ton Graphics.
Ha oui il faut que tu cast ton objet Graphics en Graphics2D pour pouvoir le faire.

AffineTransfrom at = new AffineTransform ();
at.translate (x, 0); //Translation horizontale.
g2d.transform(at);


Le 28 mai 2009 à 21:23:51

alors deja, comment on fait faire la translation ??????
sinon, en faite, il faut que le graph donne toujours l'impression d'avancer (comme sur un oscilloscope mal reglé)

bon, je regarde tout cela ;)

ah aussi je choisie la representation en fonction de qui est selectionner dans ma list en haut a gauche.

la partie qui lance la representation et la partie qui gere ce morceau de l'IHM sont dans deux class differente.

dans ma class de l'IHM (CommandeVisu.java), je fait une methode get:

//CommandeVisu.java

public CommandeVisu()
{
		
}
public boolean getIndexList()
{
    	
    	return list.getSelectedIndex()==0; //ligne 32
        //list est ma List	
}


dans la class ou ce situe le lancement de la representation:
private CommandeVisu cv1;

puis plus bas:
if(cv1.getIndexList()) //erreur nullpointeur exeption ici //50
{
	lancement du disque
}
else
{
	lancement de la courbe
}


l'erreur
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at CommandeVisu.getIndexList(CommandeVisu.java:32)
at Visu.paint(Visu.java:50)


s'auriez vous me dire pourquoi cela ne fonctionne pas ????

merci pour vos bon conseil ;)

edit: elmh si je met 99, j'ai toujours le 1er point relier au dernier ;)


edit2:
j'ai testé le
AffineTransform at = new AffineTransform ();
at.translate (0, 50); //Translation horizontale.
g2d.transform(at);
ça marche nickel (j'ai du retouché tout mes autre positionnement mais bon, rien de bien grave ;) )
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 21:48:07

As-tu initialisé ton objet cv1 ? ça n'a pas l'air.
Pour faire la translation, lolilolight a mis une méthode lourde mais qui marche très bien dans la plupart des applis.

Difficile de t'aider plus qu'en te donnant la méthode, sinon faudrait te faire le code ^^'
Comme je suis relativement intéressé par les graphes, j'vais essayer de pondre un code dans la soirée qui te permette d'y voir plus clair peut-être.

[EDIT]
En fait je préfère ça comme méthode pour les translations :
AffineTransform sauvegarde = g.getTransform();
g.translate(x, 0);
g.setTransform(sauvegarde);
Le 28 mai 2009 à 21:51:44

le positionnement est géré elmh ;)
il ne me reste plus qu'a faire le "pousse-pousse" du graph et je cherche ce que tu veux dire par "initialisé cv1"

dans tous les cas, merci beaucoup pour votre aide ;)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 21:55:01

Initialiser une variable, c'est les bases de la conception objet :p
Objet variable = new Objet();

Ceci est une initialisation possible.
Le 28 mai 2009 à 21:57:00

ok, oui, lol :)
bon, j'avais bien fait l'initialisation ;)

cv1=new CommandeVisu();
//dans le constructeur de ma class


je test ta methode qui a l'air bien plus facile a utiliser ;)


edit:
dans ma class CommandeVisu j'ai essayé de faire
public CommandeVisu(Visu visu){
    	
    	visu.dessineDisque(); //j'ai bien sur crée la methode dans l'autre class
    }


et je tombe sur le même genre d'erreur......

edit:
public void dessineDisque()
	{
		int angle= (int) (-1.8*valCour2);
		// permet de faire varier l'angle entre 0 et 180
		System.out.println("ici"); //s'affiche
		g2.fillArc(30, 20, 200,150,-180, angle);//sur cette ligne la que sa plante.....
//g2 est un objet Gaphics (comme g)
	}


help me please
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 23:06:05

Ouh la tu le récupères d'où ton objet Graphics ? J'espère que c'est pas une variable d'instance XD
Préfère un truc comme ceci :
public void dessineDisque(Graphics2D g)
{
	int angle = (int) (-1.8*valCour2);
	System.out.println("ici"); //s'affiche
	g.fillArc(30, 20, 200, 150, -180, angle);
}


Sinon j'ai bientôt fini mon petit code d'exemple, mais là je galère avec les Thread : je n'arrive pas à contrôler l'affichage toutes les 50ms.
Rah c'est pas sérieux ça j'ai résolu ce problème y'a quelques mois et à force de pu coder ben je sais pu ^^'
Le 28 mai 2009 à 23:09:22

Pour les Timer, le plus simple c'est la classe Timer de Swing ou celle de utils ; pas besoin de faire manuellement un Thread (J'opterais pour Swing ici, la classe Timer de utils est plus riche, trop pour un cas comme ça).

http://java.sun.com/javase/6/docs/api/ [...] ng/Timer.html

Elle se gère avec un simple ActionListener.
Le 28 mai 2009 à 23:20:58

je recupere le g2 comme ceci

private Graphics g2;
public void paint(Graphics g) {

g2=g;
//......
}

sa ne va pas?

edit: je t'envoie le code complet des deux class par MP
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 28 mai 2009 à 23:33:01

Les Graphics sont des objets lourds, temporaires. Il vaut mieux éviter de les stocker (Et donc les passer en paramètre aux méthodes qui en ont besoin. Comme ça, dès que c'est fini, il peut être nettoyé).
Le 28 mai 2009 à 23:42:45

j'ai le même probleme lorsque je passe en parametre....

private Graphics g3;

//.....

visu.DessineDisque(g3);

même probleme....
je ne comprend pas...
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 0:02:29

Normalement tu dois dessiner seulement dans paintComponent.
Donc avec la méthode dessineDisque(graphics2D) que je t'ai donnée, t'as pu qu'à faire :
public void paint(Graphics g2) {
   Graphics2D g = (Graphics2D)g2;
   super.paint(g);
   dessineDisque(g);
}

Ca c'est la manière la plus propre de faire. Si tu utilises une instance explicite de Graphics comme tu le fais, c'est signe d'une mauvaise conception. Enfin si jamais tu veux l'utiliser, il faut que tu libères les ressources utilisées avec g.dispose();

De mon côté je me bâts avec mon code pour qu'il arrête d'écraser les précédents dessins. J'ai bien des solutions en tête mais de toute manière mon code va être vraiment pourri.
Le 29 mai 2009 à 0:07:10

ok, mais, comment veut tu que j'utilise dessineDisque depuis une autre class???
car a ce que je comprend, je ne peut utiliser dessineDisque que dans ma class Visu???

si dans ma class visu, ma methode marche, mais, par contre, depuis une autre class, sa plante...

donc, soit j'ai rien comprit, soit, je ne sais pas comment faire (j'ai vraiment testé plein de truc....)

merci de ton aide

edit: je croit que j'ai comprit ce que tu veux dire, je test ;)

edit2: et bien, non, j'ai rien comprit, sa ne marche pas, je ne voit pas comment je peux faire pour appeler dessineDisque (avec ou sans argument sa plante)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 0:16:54

Tu ne peux utiliser dessineDisque(Graphics) que depuis une classe qui te délivre un objet Graphics (dans notre cas un Component comme Canvas par exemple).
A partir de là aucun soucis pour dessiner normalement !?
Le 29 mai 2009 à 0:21:56

le probleme c'est que ma class (d'appel de la fonction) est deja extends panel donc, elle ne me crée pas d'objet Graphics.....

je t'ai envoyé le source de mes deux class sur tes message privée ;)

la, je suis decouragé, je ne comprend pas.....
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 0:36:22

Mais si mais si, Panel est un Component (Panel extends Component ) et donc le seul objet Graphics que tu devrais manipuler se situer dans la méthode paint(Graphics) que tu vas surcharger, et pas ailleurs !

class1 extends Panel {
  //[...]
  public void paint(Graphics g) {
    super.paint(g);
    objet.dessineDisque(g);
  }

}

class2 extends Panel {
  //[...]
  public void paint(Graphics g) {
    super.paint(g);
    objet.dessineDisque(g);
  }

}


Bien sûr comme ta méthode dessineDisque n'est pas statique elle doit s'opérer sur une instance de la classe qui implémente cette méthode (sur un objet Visu si je me trompe pas).
Bon dans ton cas Visu est un Canvas qui possède la méthode dessineDisque. Mais donc pourquoi voudrais-tu utiliser la méthode dessineDisque de ta classe Visu dans une autre classe puisque ta méthode a besoin des données de sa classe ? Si tu souhaites avoir la méthode dessineDisque dans une autre classe, soit tu déclares tes données (tes points x et tes points y) en static en n'oubliant pas de déclarer Visu.dessineDisque() en static aussi, soit tu copies les données dans la classe (mais c'est un peu bête dans ce cas, autant préférer la première méthode), soit tu crées des données différentes et dans ce cas tu auras à implémenter une nouvelle méthode dessineDisque dans la classe qui en aura besoin.

J'espère être clair parce que c'est pas évident à expliquer.
Remarque d'un autre côté si tu ne comprends pas encore ces notions, je te conseille d'arrêter la programmation évènementielle quelques moments pour bien assimiler les concepts de base de la POO.

Avis de zéro :)
Le 29 mai 2009 à 19:58:38

je croit que tu n'as pas comprit pourquoi je voulai appeler la methode dessine.... depuis une autre class.
la class CommandVisu, crée une IHM, dans, cette IHM, j'ai une list.
cette liste doit me permettre de choisir entre la representation en demi-disque et en graph.

donc, pour cela, j'ai une class Visu extends canvas, qui me permet de faire ces 2 methode de dessin.

dans ma class commandevisu (dans le constructeur même) j'ai un objet de type visu qui est passé en argument.

donc, je veux me servir de ce visu passer en argument pour lancé l'une ou l'autre des methode.

pour cela, je fait vius2=visu; (visu, objet de type visu, mais accecible par toute ma class CommandeVisu)

pour dans mon actionPerformed de ma list, je veux faire soit un visu2.dessineDisque ou bien un visu2.dessineCourbe

donc, tu comprend bien que, je suis obligé de lancé les methode depuis ma class Visu.

je ne sais pas si je suis trés clair.....

enfin, merci a toi ;)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 20:11:25

Ok très bien alors relis ce que j'ai écrit.
Tu n'utilises dessineTruc() que dans la méthode paint(Graphics).
Donc oui problème comment faire ça depuis l'actionPerformed ?
Et bien voici une solution :
Crée une variable boolean isCourbeChoisie. Dans ton actionPerformed de ta list, change le boolean en conséquence, et puis appelle repaint() ! Cette méthode est là pour ça.
Maintenant dans ton paint(Graphics) mets tes méthodes dessineTruc() dans des conditions du genre if(isCourbeChoisie == true) visu.dessineCourbe(g);

public void paint(Graphics g2) {
  super.paint(g2);
  Graphics2D g = (Graphics2D)g2;
  if(isCourbeChoisie) visu.dessineCourbe(g);
  else visu.dessineDisque(g);
}


Si ça ne t'aide toujours pas, exprime-toi mieux ^^
Le 29 mai 2009 à 21:13:09

oui, je suis vraiment trop c** .......

enfin, ça marche :)

par contre, j'ai un petit delire, ma variable boolean change bien de valeur suivant ma list, elle change bien de valeur , mais, juste aprés elle reprend sa valeur initiale.... donc, quand je fait mon get dessus, j'ai toujour la même courbe ...
je doit faire une connerie quelque part, je cherche, et je te tiens au courant.


merci, vraiment pour ton aide ;)
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 21:20:54

Y'a pas de problème.
Si tu repostes par contre, tu voudrais dire où tu en es dans tes problèmes parce que y'en a eu des dizaines.
Donc une petite mise à jour de ce que tu n'as pas réussi à faire serait pas mal.

Par ailleurs je me suis cassé la tête hier à pousser le graphe comme tu le voulais, ben j'ai jamais réussi. Enfin j'étais fatigué ça doit être ça :p J'ai une solution en théorie mais j'ai eu du mal à l'appliquer...
C'est assez bordélique à faire je trouve.
Le 29 mai 2009 à 21:31:28

d'accord merci ;)

donc la petite MAJ:
il reste:

le probleme du boolean qui reprend sa valeur par defaut
comment faire du "pousse-pousse" avec la courbe
et enfin, comment empecher a la création du graph que le premier point soit relier au dernier


voila voila ;)

donc, alors pour le probleme du boolean, voici le code qui correspond:
private boolean courbeChoisie=true;

public boolean isCourbeChoisie() {
		return courbeChoisie;
}



	@Override
	public void itemStateChanged(ItemEvent arg0) {
		// TODO Auto-generated method stub
		if(list.getSelectedIndex()==0)
    	        {
			courbeChoisie=true;

                }
    	        else
    	        {
			courbeChoisie=false;
    	        }
        }


je ne touche au boolean que ici....

et pour le graph j'utilise la methode drawPolyline

voila, merci a toi, encore une fois ;)
je retourne cherché de mon coté ;)


edit:
j'ai placer quelque System.out....
et je me retrouve avec cela

dans le get boolean courbeChoisie= true
dans le else CommandeVisu courbeChoisie= false
dans le get boolean courbeChoisie= true

donc, on voit bien que si je passe le boolean courbeChoisie a false, il repasse a true avant de rentré dans le get.....

je ne voit vraiment pas ou.....
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...
Le 29 mai 2009 à 22:00:23

Pour le truc du graphe t'as du merdé dans le tableau des coordonnées, parce que moi j'ai aucun soucis en initialisant les valeurs clairement.
Ca vient sûrement de ton tableau de valeurs que tu passes à la méthode drawPolyline().

Le pousse-pousse ça va être dur pour moi de t'expliquer, étant donné que j'ai du mal aussi. Si quelqu'un a une bonne solution, qu'il se manifeste ^^'

Et le truc du boolean c'est sûrement dû à une mauvaise compréhension du Listener (comment fonctionne la méthode itemStateChanged en gros). Je n'en ai jamais utilisé mais je pense que si tu fais des tests tu devrais vite trouver.
Le 29 mai 2009 à 22:13:46

je vais regardé cela pour les tableau du graph ;)

par contre, sa ne vient pas de la methode itemStateChanged
car j'ai essayé de changer par un actionlistener et j'ai le même probleme, je t'envoie le source complet de CommandeVisu en MP (comme sa, si tu vois un truc bizarre ;) )

je te remercie ;)


edit: je ne pense pas que le trait viennent de mes tableaux je fait comme ceci

dans le constructeur de ma class:
k=j;

la methode qui me permet de reuperer la valeur generé par le .class
k=k+2;
j++;
y[j] = valCour2; //valCOur2 est la valeur retournée par le .class
x[j] = k;

//x[] tableau axe x
//y[] tableau axe y

//k et j sont remit a zero lorsque le tableau de 100 point est plein.

donc, je ne voit pas d'ou vient le probleme....
Le jour où Microsoft fera des choses qui ne plantent pas, ça sera des clous ...

dessiner en java

× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
  • Editeur
  • Markdown