salut,
serait il possible avec swing de dessiner ce composant qui servira comme indicateur pour des données aéronautiques ... quelqu'un peut il me donner un coup de main svp ?
merci
Version imprimable
salut,
serait il possible avec swing de dessiner ce composant qui servira comme indicateur pour des données aéronautiques ... quelqu'un peut il me donner un coup de main svp ?
merci
Le mieux ça serait pas de faire une image du cadran, plusieur images de fleches suivant plusieur position, et les déplacer en fonction de tes données ?
Parce que dessiner ça en swing ça va être violent :?
Déja tu vas commencer par modéliser ton composant au niveau code, c'est à dire un model contenant les diverses informations de base, cad les diverses valeurs qui seront affichée (et donc les setters qui vont bien).
La deuxième chose à faire est de décomposer les divers éléments dont tu auras besoin.
Donc grosso merdo:
Pour simplifier la chose au départ je te recommande de faire une graduation simple, c'est à dire droite au lieu de courbe
- Une courbe et se graduations. => drawCurve et drawLine (utilisatiion de (co)sinus pour calculer l'inclinaison en fonction de ta courbe) sur les Graphics de ton composants
- Une flèche (probablement une image que sur laquelle tu devras effectuer une rotation) récupération des graphics de ton image, rotation en fonction de la valeur puis drawImage sur ton composant
- Les cadran de gauche et du bas sont composés de deux éléments: un rectangle et une String (drawRectangle et drawString sur les graphics de ton composant)
- Pas mal d'huile de coude.
Pour aérer ton code essaye de découper les différents dessins en plusieurs méthodes du genre
& cieCode:drawArrow(Graphics g)
Bonne chance et bienvenu dans le monde de java2D
merci sinok :) mais je t'avoue que c'est encore du chinosi pour moi ..pourrais tu illustrer ce que tu as dit par un petit code qui pourra me servir de base ...je t'avoue que c'est un peu bloquant pour moi
et encore merci
On va dire que faire un code de base ne serait pas forcément très rapide, puis là je suis au taf, donc pas forcément le bon endroit pour le faire... Ce soir peut être
En attendant commences par te former de base sur le dessin en java: http://duj.developpez.com/tutoriels/java/dessin/intro/
Et à lire les tutos java2D de Sun:
http://java.sun.com/docs/books/tutorial/2d/TOC.html
Ainsi que la javadoc des classes Graphics et Graphics2D
Bon pour te donner une première idée de la modélisation (pas trop envie de me plonger la tête dans les maths ce soir, en ce moment en général)
Voilà ce que ça donne
Le modèle:
Le listener et l'event associé:Code:
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 import javax.swing.event.EventListenerList; public class GraduationModel { private EventListenerList listeners; private int value; public GraduationModel() { super(); this.listeners = new EventListenerList(); } public int getValue() { return value; } public void setValue(int value) { int oldValue = this.value; this.value = value; fireValueChanged(oldValue,value); } protected void fireValueChanged(int oldValue, int newValue) { GraduationEvent event = null; for(GraduationListener listener : getValueListeners()) { if(event == null) event = new GraduationEvent(oldValue, newValue); listener.valueChanged(event); } } public GraduationListener[] getValueListeners() { // TODO Auto-generated method stub return listeners.getListeners(GraduationListener.class); } public void addGraduateListener(GraduationListener l) { listeners.add(GraduationListener.class, l); } }
Code:
1
2
3
4
5
6
7
8
9 import java.util.EventListener; public interface GraduationListener extends EventListener{ public void valueChanged(GraduationEvent e); }
Le composant faisant le dessinCode:
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 /** * @author sinok * */ public class GraduationEvent { private int oldValue; private int newValue; /** * @param oldValue * @param newValue */ GraduationEvent(int oldValue, int newValue) { this.oldValue = oldValue; this.newValue = newValue; } /** * @return */ public int getOldValue() { return oldValue; } /** * @return */ public int getNewValue() { return newValue; } }
En ce qui concerne le dessin sur le composant c'est du vite fait mal fait (c'est moche, c'est une graduation droite & cie...Code:
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132 import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.Timer; public class GraduationComponent extends JComponent implements GraduationListener, ActionListener{ private GraduationModel model; private int oldValue; private int newValue; private int direction; private Timer timer; private BufferedImage thumb; public GraduationModel getModel() { return model; } public void setModel(GraduationModel model) { this.model = model; } public GraduationComponent(GraduationModel model) { super(); this.model = model; this.timer = new Timer(50,this); model.addGraduateListener(this); try { thumb = ImageIO.read(getClass().getResourceAsStream("arrow.png")); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected void paintComponent(Graphics g) { // TODO Auto-generated method stub //super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; if( this.isShowing()) { drawBackground(g2d); drawGraduate(g2d); } } public void valueChanged(GraduationEvent e) { // TODO Auto-generated method stub this.oldValue = e.getOldValue(); this.newValue = e.getNewValue(); if(oldValue > newValue) { direction = -1; } else if(oldValue < newValue) { direction = 1; } else { direction = 0; } timer.start(); } public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub oldValue += direction; repaint(); if(oldValue == newValue) { timer.stop(); } } protected void drawGraduate(Graphics2D g2d) { g2d.setPaint(Color.white); g2d.drawString(String.valueOf(model.getValue()), 10, 20); g2d.drawString(String.valueOf(this.oldValue), 10, 40); g2d.draw(new Line2D.Double(150,190,150,10)); for(int i = 10; i<191; i+=10) { if(i%20 == 10) { g2d.draw(new Line2D.Double(140,i,150,i)); } else { g2d.draw(new Line2D.Double(145,i,150,i)); } } g2d.drawImage(thumb,140-thumb.getWidth()-10,190-(thumb.getHeight()/2)-oldValue,thumb.getWidth(), thumb.getHeight(),null); } protected void drawBackground(Graphics2D g2d) { g2d.setPaint(Color.black); g2d.fill(new Rectangle2D.Double(0,0,getWidth()-1,getHeight()-1)); } public static void main(String[] args) { final GraduationModel m = new GraduationModel(); m.setValue(0); GraduationComponent c = new GraduationComponent(m); JFrame f = new JFrame(); f.add(c); f.setSize(200,200); f.setLocationRelativeTo(null); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setVisible(true); Timer t = new Timer(5000,new ActionListener() { public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub m.setValue(m.getValue()+10); } }); t.start(); } }
Mais le'essentiel pour toi est déja de comprendre les bases de la création d'un composant. A toi de faire le reste (calculs sur les rotations, courbes et les dessiner)
Vais pas te macher entièrement le taf non plus
Si tu as des questions... (désolé je n'ais pas franchement eu le temps de commenter mon code...)
Les methodes indiquees precedement sont bonnes mais il n'est pas vraiment necessaire que la fleche soit une image (surtout si elle est si simple) ; une simple Shape (un GeneralPath ou un Polygon) fera tout aussi bien l'affaire. Apres c'est la meme methode : utiliser une transformation affine pour la dessiner avec le bon angle.
Principe de base en 2D : en general, ne pas se prendre la tete en caculs complexe. Si tu sais tout dessiner a l'horizontal (resp a la verticale) autour de (0, 0) alors tu peux tout dessiner sous n'importe quel angle et a n'importe quel emplacement avec des transformations affines (et leur transformations inverses) de rotation et de translation (resp pour des transformation affines autre que des rotations).
Merci a vous deux c'est tres gentil :
cependant si j'ai bien compri sinok dans ton code tu as un timer qui te gere le deplacement de al fleche selon la valeur générée...cependant j'ai une petite question pourquoi quand j'oblige le timer a s'arrêter quand j'atteint une valeur X ( valeur max par exemple ) il continue a generer les valeurs et la fleche continue a remonter ? :(
merci
Code:
1
2
3
4
5
6
7
8
9
10
11 public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub oldValue += direction; repaint(); if((oldValue == newValue) || (maxValue == newValue )) // ou maxvalue est une valeur private initilaisée a 200 par exemple timer.stop(); }
L'action performed du composant ne gère que l'animation de la flèche (c'est à dire qu'il va depuis l'ancienne valeur du model vers la nouvelle...)
C'est dans le main que je change les valeurs du model (c'est pas propre mais j'avais juste besoin de tester ^^...)
c'est bon il fallait juste agir a ce niveau:
cependant bouye peut me dire si les transformation sont le seul moyen pour faire deplacer une shape ou image comme mon cas précis?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 public void valueChanged(GraduationEvent e) { // TODO Auto-generated method stub this.oldValue = e.getOldValue(); this.newValue = e.getNewValue(); if(oldValue > newValue) { direction = -1; } else if(oldValue < newValue) { direction = 1; } else { direction = 0; } if(maxValue < newValue ) // ici timer.stop(); else timer.start(); }
merci
Non tu peux aussi faire des calculs a la main pour chacune des positions, mais ca devient vite bien prise de tete plus encore quand on a plein de points et de transformations a effectuer.
C'est plus simple soit en manipulant directement le graphics (les methodes g.rotate(), etc... sont traduites en terme de transformation affine) soit en utilisant AffineTransform a nouveau soit directement sur le graphics (g.setTransform()), soit sur les formes de maniere a produire des formes intermediaires transformees (t.createTransformedShape()).
Personelement je prefere les appliquer sur le graphics.
Apres l'important c'est toujours de se souvenir quelle est (où est) l'origine actuelle du repere et quelle est la derniere transformation effectuee.
Tu verras a l'usage que les indices de rendu du graphics ont des effets sur le rendu final nottament :
RenderingHints.KEY_RENDERING - rendu general
RenderingHints.KEY_INTERPOLATION - interpolation des couleurs (solides) des images transformees (preferrer RenderingHints.VALUE_INTERPOLATION_BILINEAR a RenderingHints.VALUE_INTERPOLATION_BICUBIC car elle est plus rapide et la 2nde, bien que de meilleur qualite en theorie, n'offre pas de resultats visibles flagrants).
RenderingHints.KEY_ANTIALIASING - aliasing des formes
ok merci :)
dans ce cas que suggere tu pour afficher une shape comme la fleche dont tu as parlé ...je veux dire pourquoi la fonction rotate par exemple doit être invoquée avant de dessiner un composant? tout ce que je veux c'est faire pivoter une flehe par rapport au centre d l'ecran ...comme l'aiguille d'une montre quoi mais je n'y arrive pas :(
La premiere etape consiste a se creer une Shape de fleche qui peut etre reutilisee ailleurs. On centrera la queue de la fleche sur O (0, 0).
Cela peut se faire avec un Polygon ou un GeneralPath :
http://img124.imageshack.us/img124/7826/arrowib4.png
Pour connaitre les coordonnees des points a reutiliser, pas de probleme :Code:
1
2
3
4
5
6
7
8 GeneralPath path = new GeneralPath(); path.moveTo(i1.x, i1.y); path.lineTo(i2.x, i2.y); path.lineTo(i3.x, i3.y); ... path.curveTo(i8.x, i8.y, i9.x, i9.y, i1.x, i1.y); path.close(); Shape arrow = path;
- dessiner une fleche dans un logiciel de dessin bitmap et relever les coordonnees des pixels des sommets.
- dessiner une fleche dans un logiciel de dessin vectoriel et relever les coordonnes des sommets et points de controle.
- encore plus simple : dessiner une fleche sur du papier quadrille, ex : un calepin.
Ensuite, nous desirons avoir ceci :
http://img478.imageshack.us/img478/4607/06aw2.png
En partant de ceci. Le cadre denote la surface d'affichage (du JPanel par exemple) dont l'origine est dans le coin superieur gauche.
http://img19.imageshack.us/img19/8356/01pm6.png
Tout d'abord nous faisons une translation du repere jusqu'au point ou devra se positionner notre queue de fleche. Note comme la zone d'affichage a ete transformee (cadre violet - c'est pour ca qu'il faut toujours penser a annuler ses transformation).
http://img267.imageshack.us/img267/5317/02cg9.pngCode:g.translate(c.x, c.y);
Ensuite nous effectuons notre rotation suivant le bon angle.
http://img267.imageshack.us/img267/2948/03wz1.pngCode:g.rotate(theta);
Nous dessinons ensuite notre jolie fleche horizontale toute simple. Mais il nous faut revenir au repere d'origine, en effet si jamais nous arretons le dessin ici, nous verrons juste une demi fleche horizontale affichee a l'ecran.
http://img406.imageshack.us/img406/5548/04ut2.pngCode:
1
2 g.setColor(Color.BLACK); g.fill(arrow);
Nous effectuons la rotation inverse. Miracle notre fleche est correctement orientee. Attention cependant l'origine du repere n'est pas correctement positionnee. Si jamais nous arretons le dessin ici seul le bout de la queue de la fleche apparaitra a l'ecran.
http://img393.imageshack.us/img393/9232/05kb2.pngCode:g.rotate(-theta);
Nous effectuons donc la translation inverse pour repositionner correctement l'origine. Et voila !
http://img478.imageshack.us/img478/4607/06aw2.pngCode:g.translate(-c.x, -c.y);
:king:
Ainsi donc si tu n'annules pas tes transformations, tu peux tout simplement avoir une fleche dessinee avec le bon angle mais qui se trouve en fait completement en dehors de ton espace d'affichage.
Attention egalement lorsque tu travailles avec des doubles ou des floats tu peux avoir des erreurs d'arrondis ce qui fait que en fait en annulant plusieurs rotations successives, etc... tu peux ne pas tout a fait revenir a l'horizontal. Une methode consiste donc a sauvegarder la transformation du graphics par exemple au lieu de :
Faire :Code:
1
2
3 g.rotate(theta); ... g.rotate(-theta);
Autre chose a se rappeler : l'orientation de l'axe des Y est inverse de celle qu'on voit a l'ecole ; ca veut dire egalement que le cercle trigonometrique est donc dans le sens des aiguilles d'une montre (a l'opposee donc de ce qu'on voit a l'ecole egalement).Code:
1
2
3
4 AffineTransform oldT = g.getTransform(); g.rotate(theta); ... g.setTransform(oldT);
Ensuite, si tu veux travaille avec une bitmap pour dessiner ta fleche... ca marche pareil !
oh violence, ça va le taf chez les Kanaks ^^
?? Pour ce qui m'ennuie en ce moment au boulot, voir http://www.developpez.net/forums/sho...42&postcount=1
Un petit exemple tres vite fait justement, plus besoin de se casser la tete pour dessiner des formes complexes.
http://img407.imageshack.us/img407/2012/image10to3.jpgCode:
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230 package test; import java.awt.*; import java.awt.geom.*; import java.awt.event.*; import java.awt.font.*; import java.awt.image.*; import javax.swing.*; import java.util.*; /** * <p>Title: </p> * * <p>Description: </p> * * <p>Copyright: Copyright (c) 2006</p> * * <p>Company: </p> * * @author not attributable * @version 1.0 */ class Clock extends JPanel implements ActionListener { Ellipse2D.Double circle = new Ellipse2D.Double(); Line2D.Double line = new Line2D.Double(); Shape arrow = null; Calendar calendar = GregorianCalendar.getInstance(); javax.swing.Timer timer; public Clock() { super(); // Create initial arrow shape. GeneralPath path = new GeneralPath(); path.setWindingRule(GeneralPath.WIND_EVEN_ODD); path.moveTo(54.81f, 286.50f); path.curveTo(63f, 243f, 49.54f, 213.88f, 49.54f, 213.88f); path.curveTo(33, 198, 38.14f, 233.32f, 38.14f, 233.32f); path.curveTo(23, 204, 26, 150, 26.51f, 136.40f); path.curveTo(28, 59, 65.64f, 12.59f, 65.64f, 12.59f); path.curveTo(12, 125, 70.40f, 207.45f, 70.40f, 207.45f); path.curveTo(59, 199, 63.63f, 219.48f, 63.63f, 219.48f); path.curveTo(70, 257, 54.81f, 286.50f, 54.81f, 286.50f); path.closePath(); path.moveTo(38.85f, 192.72f); path.curveTo(38.85f, 192.72f, 35, 162, 37.64f, 155.94f); path.curveTo(37.64f, 155.94f, 44, 183, 51.76f, 196.26f); path.curveTo(51.76f, 196.26f, 44, 190, 38.85f, 192.72f); path.closePath(); path.moveTo(72.67f, 268.82f); path.curveTo(85, 218, 74, 203, 63.75f, 177.85f); path.curveTo(38, 118, 51.90f, 81.73f, 51.90f, 81.73f); path.curveTo(43, 123, 68, 156, 73.17f, 165.67f); path.curveTo(100, 225, 72.67f, 268.82f, 72.67f, 268.82f); path.closePath(); // The arrow tail was not centered around (0, 0), now it is. AffineTransform t = AffineTransform.getTranslateInstance( -55, -182); arrow = t.createTransformedShape(path); } /** * {@inheritDoc} */ public void actionPerformed(ActionEvent event) { repaint(); } /** * {@inheritDoc} */ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Insets insets = getInsets(); Dimension size = getSize(); int width = size.width - (insets.left + insets.right); int height = size.height - (insets.top + insets.bottom); Graphics2D g2d = (Graphics2D) g.create(insets.left, insets.top, width, height); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d.setColor(getBackground()); g2d.fillRect(0, 0, width, height); int diameter = Math.min(width, height) - 50; if (diameter > 0) { long date = System.currentTimeMillis(); calendar.setTimeInMillis(date); int hours = calendar.get(Calendar.HOUR_OF_DAY); int minutes = calendar.get(Calendar.MINUTE); int seconds = calendar.get(Calendar.SECOND); g2d.setColor(getForeground()); g2d.drawString(hours + ":" + minutes + ":" + seconds, 100, 100); double cX = width / 2.0; double cY = height / 2.0; double radius = diameter / 2.0; g2d.translate(cX, cY); circle.setFrameFromCenter(0, 0, radius, radius); g2d.setPaint(Color.WHITE); g2d.fill(circle); g2d.setPaint(getForeground()); g2d.draw(circle); circle.setFrameFromCenter(radius / 2.0, radius / 2.0, 3 * radius / 4.0, 3 * radius / 4.0); g2d.setPaint(Color.WHITE); g2d.fill(circle); g2d.setPaint(getForeground()); g2d.draw(circle); circle.setFrameFromCenter( -radius / 2.0, radius / 2.0, -3 * radius / 4.0, 3 * radius / 4.0); g2d.setPaint(Color.WHITE); g2d.fill(circle); g2d.setPaint(getForeground()); g2d.draw(circle); circle.setFrameFromCenter(0, -radius / 2.0, radius / 4.0, -radius / 4.0); g2d.setPaint(Color.WHITE); g2d.fill(circle); g2d.setPaint(getForeground()); g2d.draw(circle); drawLabelOnTop(g2d, "Chronometer", radius / 2.0, radius / 4.0 - 5); drawLabelOnTop(g2d, "Altitude", -radius / 2.0, radius / 4.0 - 5); drawLabelOnTop(g2d, "Presure", 0, -3 * radius / 4.0 - 5); double theta = 2 * Math.PI / 12; Font font = g2d.getFont(); for (int i = 1; i <= 12; i++) { g2d.rotate(theta); line.setLine(0, -radius, 0, -radius - 5); String label = String.valueOf(i); drawLabelOnTop(g2d, label, 0, -radius - 10); g2d.draw(line); } Rectangle2D arrowBounds = arrow.getBounds2D(); double arrowLength = -arrowBounds.getY(); double scale = (0.80 * radius) / arrowLength; double hourAngle = (hours % 12) * 2 * Math.PI / 12; double minutesAngle = minutes * 2 * Math.PI / 60; double secondsAngle = seconds * 2 * Math.PI / 60; AffineTransform oldT = g2d.getTransform(); g2d.rotate(minutesAngle); // Scale+shrink+mirror on X axis & scale on Y axis. g2d.scale( -0.5 * scale, scale); g2d.setPaint(getForeground().brighter().brighter().brighter().brighter()); g2d.fill(arrow); drawLabelOnTop(g2d, "Minutes", 0, -arrowLength); //g2d.draw(arrowBounds); g2d.setTransform(oldT); g2d.rotate(hourAngle); // Scale on both axis. g2d.scale(0.66 * scale, 0.66 * scale); g2d.setPaint(getForeground()); g2d.fill(arrow); drawLabelOnTop(g2d, "Hours", 0, -arrowLength); //g2d.draw(arrowBounds); g2d.setTransform(oldT); g2d.rotate(secondsAngle); g2d.setPaint(getForeground().brighter().brighter()); // One simple vertical straight line. line.setLine(0, 0, 0, -0.95 * radius); g2d.draw(line); drawLabelOnTop(g2d, "Seconds", 0, -0.95 * radius); g2d.setTransform(oldT); // Chronometer. g2d.translate(radius / 2.0, radius / 2.0); g2d.rotate(2 * Math.PI / 3.0); line.setLine(0, 0, 0, 0.95 * radius / 4.0); g2d.setPaint(getForeground()); g2d.draw(line); g2d.setTransform(oldT); // Altitude g2d.translate( -radius / 2.0, radius / 2.0); g2d.rotate(2 * Math.PI / 6.0); line.setLine(0, 0, 0, 0.95 * radius / 4.0); g2d.setPaint(getForeground()); g2d.draw(line); g2d.setTransform(oldT); //Presure. g2d.translate(0, -radius / 2.0); g2d.rotate(2 * Math.PI / 4.0); line.setLine(0, 0, 0, 0.95 * radius / 4.0); g2d.setPaint(getForeground()); g2d.draw(line); g2d.setTransform(oldT); } // Cancel all pending transforms. g2d.dispose(); } protected void drawLabelOnTop(Graphics2D g2d, String label, double x, double y) { Font font = g2d.getFont(); Rectangle2D labelBound = font.getStringBounds(label, g2d.getFontRenderContext()); LineMetrics lineMetrics = font.getLineMetrics(label, g2d.getFontRenderContext()); g2d.drawString(label, (float) (x - labelBound.getWidth() / 2.0), (float) (y - lineMetrics.getDescent())); } /** Start (or restart) timer. */ public synchronized void start() { if (timer == null) { timer = new javax.swing.Timer(1000, this); timer.start(); } else { timer.restart(); } } /** Stop timer. */ public synchronized void stop() { timer.stop(); } /** * @param args Arguments from the command-line. */ public static void main(String ...args) { // Start at EDT. SwingUtilities.invokeLater(new Runnable() { /** * {@inheritDoc} */ public void run() { Clock clock = new Clock(); clock.start(); JFrame frame = new JFrame("Clock"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(clock, BorderLayout.CENTER); frame.pack(); frame.setVisible(true); } }); } }
Salut,
pas mal :)
mais si l'on souhaite faire fonctionner tes indicateurs ( altitude, pressure...) on fait comment?...des threads ou un seul? je suis vraiement interessé!
merci
Rien de plus special que le fait d'avoir une propriete/une variable equivalente pour chacune des valeurs. Sinon un Timer Swing si jamais il faut faire des annimations avec des fleches qui bougent de maniere "realiste". Apres divers frameworks sont en devellopement pour faire des animations de maniere plus avancee mais je ne suis pas trop la chose.
Chouette :ccool:
Rien de plus en théorie/facon de parler :
Il faut quand même modifier ca pour caculer le bon angle en fonction de l'altitude. Bon ce n'est pas vraiment la partie la plus compliquée à faire. Et mettre les getter/setter sur la propriété/membre créée.Code:
1
2
3
4
5
6
7 // Altitude g2d.translate( -radius / 2.0, radius / 2.0); g2d.rotate(2 * Math.PI / 6.0); line.setLine(0, 0, 0, 0.95 * radius / 4.0); g2d.setPaint(getForeground()); g2d.draw(line); g2d.setTransform(oldT);
Après un "vrai" altimètre devrai disposer d'une graduation sur le cadran (voir comment faire celle de l'horloge) et éventuellement un indice de multiplication via un compteur sous les aiguilles ou d'un petite aiguille indiquant la multiplication (si on fait plusieurs tours du cadran).
De même pour la pression alors que le chronomère aura tendance à avoir une autre aiguille mais pour les heures. Bref il y a des tas de manière de décorer/améliorer l'ensemble y compris en utilisant des bitmap ou des Painter pour obtenir un rendu plus réaliste.
L'important de cet exemple c'était surtout pour montrer que les transformations affines sont vos amies et peuvent vous simplifier la vie (même si parfois ca semble être de l'artillerie lourde). Comme je disais au début : si vous savez dessiner une forme (complexe ou pas, peu importe) à l'horizontale/verticale, vous pouvez dessiner sous n'importe quel angle/transformation affine sans avoir besoin de calculer chaque point de cette forme vous-meme (cf les fèches de la montre).