Le Immaggini
Passo1 Passo2 Passo 3
Obiettivo: Variante n. 3 aggiunta di Stick roll stop.

Altro passo avanti, faremo in modo che la manopola della versione precedente possa ruotare intorno al suo centro, ma questa volta grazie all'uso del mouse.
Classe principale eseguibile:
1 package manov3;
2
3 import java.awt.*;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.awt.event.ItemEvent;
7 import java.awt.event.ItemListener;
8 import javax.swing.event.ChangeListener;
9 import javax.swing.event.ChangeEvent;
10 import java.util.Locale;
11 import javax.swing.*;
12
13 public class ManoV3 extends JFrame{
14 private JButton jb,jx;
15 private JToggleButton jg;
16 private JSpinner jt,js;
17 private JLabel jval;
18 private JLabel jv,jgra;
19 private int flg=0,lx,ly,lw,mx,my,cox,coy,vel=10;
20 private double gra=0,inc=0.5;
21 private Timer tm;
22 private String val;
23 public MyIcon3 mn;
24 public JPanel radioPanel;
25
26 public ManoV3() {
27 Locale.setDefault(Locale.Category.FORMAT, Locale.ENGLISH);
28
29 setTitle("Manopola Ruotante");
30 setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
31 getContentPane().setBackground(Color.white);
32 setLayout(null);
33 setSize(530, 500);
34 setLocationRelativeTo(null);
35
36
37 jb = new JButton("Passo");
38 jb.addActionListener(new ActionListener() {
39 public void actionPerformed(ActionEvent evt) {
40 jg.setText("Start");
41 jg.setSelected(false);
42 tm.stop();
43 mn.varia();
44 val=mn.getVal();
45 jv.setText(val);
46 }
47 });
48 jb.setBounds(15, 10, 80, 23);
49 add(jb);
50
51
52 jx = new JButton("Direzione");
53
54 jx.addActionListener(new ActionListener() {
55 public void actionPerformed(ActionEvent evt) {
56 mn.chgDir();
57 }
58 });
59 jx.setBounds(100, 10, 90, 23);
60 add(jx);
61
62
63 js = new JSpinner();
64 js.setLocale(Locale.ENGLISH);
65 js.setModel(new SpinnerNumberModel(inc,0.0d,360.0d,0.1d));
66 js.setFont(new java.awt.Font("Tahoma", 1, 14));
67 js.addChangeListener(new ChangeListener() {
68 public void stateChanged(ChangeEvent evt) {
69 inc = Double.parseDouble (""+js.getValue());
70 mn.setInc(inc);
71 }
72 });
73 js.setBounds(247, 9, 60, 25);
74 add(js);
75
76
77 jt = new JSpinner(new SpinnerNumberModel(vel,1,2000,5));
78 jt.setFont(new java.awt.Font("Tahoma", 1, 14));
79 jt.addChangeListener(new ChangeListener() {
80 public void stateChanged(ChangeEvent evt) {
81 vel = Integer.parseInt(""+jt.getValue());
82 tm.setDelay(vel);
83 tm.start();
84 }
85 });
86 jt.setBounds(360, 9,60, 25);
87 add(jt);
88
89
90 jg = new JToggleButton("Start");
91 jg.addItemListener(new ItemListener() {
92 public void itemStateChanged(ItemEvent evt) {
93 int status = evt.getStateChange();
94 if(status == ItemEvent.SELECTED){
95 jg.setText("Stop");
96 tm.start();
97 }else{
98 jg.setText("Start");
99 tm.stop();
100 }
101 }
102 });
103 jg.setBounds(425, 10, 70, 23);
104 add(jg);
105
106
107 jgra = new JLabel("inc-gra");
108 jgra.setFont(new Font("Tahoma", 1, 14));
109 jgra.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
110 add(jgra);
111 jgra.setBounds(164, 10, 80, 20);
112
113
114 jval = new JLabel("inc-vel");
115 jval.setFont(new Font("Tahoma", 1, 14));
116 jval.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
117 add(jval);
118 jval.setBounds(308, 10, 50, 20);
119
120
121 jv = new JLabel("0");
122 jv.setFont(new Font("Digital-7Mono", 1, 30));
123 jv.setForeground(Color.RED);
124 jv.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
125 add(jv);
126
127
128 mn = new MyIcon3();
129 mn.setLocation(103, 86);
130 mn.setInc(inc);
131 add(mn);
132
133 setVisible(true);
134
135 cox=getContentPane().getSize().width;
136 coy=getContentPane().getSize().height;
137 mx=(cox-(mn.getWp()))/2;
138 my=(coy-(mn.getHp()))/2;
139 mn.setLocation(mx, my);
140 mn.setLocation(mx, my);
141
142
143 lw=200;
144 lx=(cox-lw)/2;
145 ly=(coy-60);
146 jv.setBounds(lx, ly, 200, 40);
147
148
149 JRadioButton stick = new JRadioButton("Stick");
150 JRadioButton roll = new JRadioButton("Roll");
151 JRadioButton stop = new JRadioButton("Stop");
152
153 ButtonGroup bG = new ButtonGroup();
154 bG.add(stick);
155 bG.add(roll);
156 bG.add(stop);
157
158 JPanel radioPanel = new JPanel(new GridLayout(0, 1));
159 radioPanel.setBackground(Color.white);
160 radioPanel.add(stick);
161 radioPanel.add(roll);
162 radioPanel.add(stop);
163 radioPanel.setBounds(18, 35, 70, 60);
164 stop.setSelected(true);
165 add(radioPanel);
166
167 stick.addActionListener(new ActionListener() {
168 public void actionPerformed(ActionEvent evt) {
169 jg.setSelected(false);
170 jg.setText("Start");
171 tm.stop();
172 mn.setFlg(1);
173 }
174 });
175 roll.addActionListener(new ActionListener() {
176 public void actionPerformed(ActionEvent evt) {
177 jg.setSelected(false);
178 jg.setText("Start");
179 tm.stop();
180 mn.setFlg(2);
181 }
182 });
183 stop.addActionListener(new ActionListener() {
184 public void actionPerformed(ActionEvent evt) {
185 mn.setFlg(0);
186 }
187 });
188 mn.addValListener(new ValEventListener() {
189 public void valChanged(ValEvent ev) {
190 jv.setText(ev.val());
191 }
192 });
193
194 tm = new Timer(vel,new ActionListener() {
195 public void actionPerformed(ActionEvent evt) {
196 mn.varia();
197 val=mn.getVal();
198 jv.setText(val);
199 }
200 });
201 }
202 public static void main(String args[]) {
203
204 java.awt.EventQueue.invokeLater(new Runnable() {
205 public void run() {
206 new ManoV3();
207 }
208 });
209 }
210 }
|
Mi limitero a sottoliare le differenze e migliorie. Sono stati aggiunti tre radionButton in gruppo (uno esclude l'atro), quando si seleziona Stick allora cliccando in un punto della manopola questa gira fino a raggiungere il punto, mentre se si seleziona Roll allora cliccando e dragando il mouse la manopola lo segue ovunque esso vada, infine se si seleziona Stop l'azione del mouse viene disabilitata e si torna alle funzionalità che già aveva la versione precedente. L'altra aggiunta è l'ascoltatore. Ogni volta che nella classe MyIcon3 viene modificato il valore dei gradi in seguito all'azione del mouse viene lanciato un evento di valChanged che porta con se una stringa formattata che indica il nuovo valore dell'angolo pronto per essere visualizzato con la label, vedi righe 188-191.
Classe esterna che disegna la manopola MyIcon3 quella che subisce più modifiche perché deve implementare il lancio degli eventi.
Classe: MyIcon3 |

|
1 package manov3;
2
3 import java.awt.Dimension;
4 import java.awt.Graphics;
5 import java.awt.Graphics2D;
6 import java.awt.Point;
7 import java.awt.event.MouseAdapter;
8 import java.awt.event.MouseEvent;
9 import java.awt.event.MouseMotionAdapter;
10 import java.net.*;
11 import java.util.EventListener;
12 import java.util.EventObject;
13 import java.util.Locale;
14 import javax.swing.*;
15
16 public class MyIcon3 extends JComponent{
17 private double gra=0,xgra,inc,dif;
18 private ImageIcon icon;
19 private int icoW,icoH,xC,yC,dir=0,flg=0;
20 private String val="";
21 private double icoWd,icoHd,nwx,nwy,gr,grc;
22
23 public MyIcon3(){
24 icon = createImageIcon("/image/mano02.png");
25 icoW = icon.getIconWidth();
26 icoH = icon.getIconHeight();
27 icoWd=(double)icoW;
28 icoHd=(double)icoH;
29 setSize(icoW,icoH);
30 setPreferredSize(new Dimension(icoW,icoH));
31
32 addMouseListener(new MouseAdapter() {
33 @Override
34 public void mousePressed(MouseEvent e) {
35 if(flg==1){
36 modAng(e.getPoint());
37 fireValChangedEvent(val);
38 repaint();
39 }
40 }
41 });
42 addMouseMotionListener(new MouseMotionAdapter() {
43 @Override
44 public void mouseDragged(MouseEvent e) {
45 if(flg==2){
46 xgra=gra;
47 modAng(e.getPoint());
48 fireValChangedEvent(val);
49 repaint();
50 }
51 }
52 });
53
54 }
55 public void paintComponent(Graphics g) {
56 super.paintComponent(g);
57 Graphics2D g2d =(Graphics2D)g;
58 xC =icoW/2;
59 yC =icoH/2;
60 g2d.translate(xC,yC);
61 g2d.rotate(Math.toRadians(gra));
62 g2d.translate(-xC,-yC);
63 icon.paintIcon(this, g2d, 0, 0);
64 }
65
66 public int getWp(){
67 return(icoW);
68 }
69 public int getHp(){
70 return(icoH);
71 }
72 public String getVal(){
73 val=String.format(new Locale("en"),"%1$.2f",gra);
74 return(val);
75 }
76 public void setInc(double ic){
77 inc=ic;
78 }
79 public void setFlg(int fg){
80 flg=fg;
81 }
82 public void chgDir(){
83 if(dir==1)dir=0; else dir=1;
84 }
85
86
87
88 public void varia(){
89 if(dir==0){
90 gra=gra+inc;
91 if(gra>360){
92 gra=gra-360;
93 }
94 }else{
95 if(gra==0){
96 gra=360-inc;
97 }else{
98 gra=gra-inc;
99 if(gra<0){
100 gra=gra+360;
101 }
102 }
103 }
104 repaint();
105 }
106 private void modAng(Point pt){
107
108 nwx=pt.x-(icoWd/2);
109 nwy=(icoHd/2)-pt.y;
110
111 gr=Math.atan2(nwy, nwx);
112
113 grc=Math.toDegrees(gr);
114
115 dif=450-grc;
116 if(dif>360)gra=dif-360; else gra=dif;
117
118 val=String.format(new Locale("en"),"%1$.2f",gra);
119
120 }
121 private void fireValChangedEvent(String st){
122 ValEvent event = new ValEvent(this,st);
123 Object[] listenersArray = listenerList.getListenerList();
124 for(int i = listenersArray.length - 2; i >= 0; i -= 2){
125 if(listenersArray[i] == ValEventListener.class){
126 ((ValEventListener)listenersArray[i+1]).valChanged(event);
127 }
128 }
129 }
130 public void addValListener(ValEventListener listener){
131 listenerList.add(ValEventListener.class, listener);
132 }
133 private ImageIcon createImageIcon(String path) {
134 URL imgURL = getClass().getResource(path);
135 if (imgURL != null) {
136 return new ImageIcon(imgURL);
137 } else {
138 System.err.println("Non è possibile trovare il file: " + path);
139 return null;
140 }
141 }
142 }
143 class ValEvent extends EventObject{
144 private String str;
145 public ValEvent(Object source,String st){
146 super(source);
147 str=st;
148 }
149 public String val(){
150 return(str);
151 }
152 }
153 interface ValEventListener extends EventListener{
154 public void valChanged(ValEvent ev);
155 } |
Le modifiche scorrendo dall'alto verso il basso sono:
- Nei campi le variabili double che prima erano state dichiarate con il relativo wrapper ora con il primitivo:
private Double wPd,hPd... con double wPd,hPd...
vedi qui per chiarimenti
- tra gli import è scomparso: import javax.swing.event.EventListenerList; e nel costruttore non c'è più l'istanza della classe listeners = new EventListenerList(); sono stati eliminati in quanto la classe JComponent da cui eredita MyIcon5 già ha istanziato una classe di nome listenerList che possiamo usare senza crearne un'altra.
- alla riga 31 abbiamo aggiunto setPreferredSize(new Dimension(wP,hP)); che permettera alla classe di essere usata anche con i layoutmanager.
- righe 33-53 ci sono due ascoltatori associati alla classe che sono in ascolto della pressione del mouse e del suo drag. quando ciò avviene vene modificato l'angolo nella nuova posizione con il metodo modAng(), poi lanciati degli eventi mediante il metodo: fireValChangedEvent(val); passando il valore del nuovo angolo in forma di stringa formattata preparata da modAng().
- sostamziale modifica al metodo modAng() grazie alla scoperta del metodo della classe Math.atan2(double y,double x) al posto di Math.atan(y/x) che praticamente fa tutto quel lavoro che avevo fatto a mano, ossia il controllo dei quadranti. Le vecchie righe di codice sono ora commentate.
- righe 137-145 il metodo fireValChangedEvent(val); che istanzia un oggetto evento passandogli il valore dell'angolo (val) e consultando la lista degli ascoltatori invia a ciascuno di essi l'evento.
- righe 146-147 il metodo addValListener che servirà ad aggiungere nuovi listener
- seguono la classe evento e l'interfaccia
|