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:

 

Classe: ManoV3

 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         //Avanza Passo Passo       
 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         //Cambio di direzione              
 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         //Spinner Incrementa il passo in gradi
 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          //Spinner invrementa la velocità in millisecondi
 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         //Start/Stop  
 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         //etichetta inc-gra 
107         jgra = new JLabel("inc-gra");
108         jgra.setFont(new Font("Tahoma", 1, 14)); // NOI18N
109         jgra.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
110         add(jgra);
111         jgra.setBounds(164, 10, 80, 20);
112 
113         //etichetta inc-vel
114         jval = new JLabel("inc-vel");
115         jval.setFont(new Font("Tahoma", 1, 14)); // NOI18N
116         jval.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
117         add(jval);
118         jval.setBounds(308, 10, 50, 20);
119 
120         //etichetta che visualizza i gradi
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         //Disegna la manopola         
128         mn = new MyIcon3();
129         mn.setLocation(103, 86);
130         mn.setInc(inc);
131         add(mn);
132 
133         setVisible(true);
134         //centra la manopola
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         //centra l'etichetta
143         lw=200;
144         lx=(cox-lw)/2;
145         ly=(coy-60); 
146         jv.setBounds(lx, ly, 200, 40); 
147         
148         //RadioButton
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         //Imposta il Timer        
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         /* Create and display the form */
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     //Metodi Pubblici
 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     //End Metodi Pubblici
 86     
 87     //controllo della posizione
 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         //trasforma in coordinate rispetto al centro con origine est
108         nwx=pt.x-(icoWd/2);
109         nwy=(icoHd/2)-pt.y;
110         //ricava angolo in radianti
111         gr=Math.atan2(nwy, nwx);        
112         //trasforma angolo da radianti in gradi centesimali
113         grc=Math.toDegrees(gr);
114         //Trasforma origine dell'angolo da est a nord
115         dif=450-grc;
116         if(dif>360)gra=dif-360; else gra=dif;
117         //if(flg==2)gra=-xgra;
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