Visualizzazione dei risultati da 1 a 7 su 7

Discussione: Animazione con Java

  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2011
    Messaggi
    43

    Animazione con Java

    Salve a tutti, ho realizzato un piccolo programma che simula un orologio, ora vorrei pero' animarlo, di modo che legga l'ora dal sistema e ridisegni ogni secondo il mio orologio.

    Ho cosi' creato la classe RandomAction che riporto di seguito:

    codice:
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    public class RandomAction extends Thread implements Runnable {
        AutoPanel autoPanel;
        boolean pause = true;
        int time = 1;                                       //1 secondo
        int hours;
        int minutes;
        int seconds;
        
        public RandomAction(AutoPanel autopanel) {
            this.autoPanel = autoPanel;
        }
        
        @Override
        public void run() {
            while(true) {
                
                    try {
                        if(!pause) {
                             this.sleep(time);
                        
                             System.out.println("sono dentro");
    
                             Calendar c = new GregorianCalendar();
                        
                             this.hours = c.get(Calendar.HOUR_OF_DAY);
                             this.minutes = c.get(Calendar.MINUTE);
                             this.seconds = c.get(Calendar.SECOND);
                        
                             this.autoPanel.t.hours = this.hours;
                             this.autoPanel.t.minutes = this.minutes;
                             this.autoPanel.t.seconds = this.seconds;
                        
                             this.autoPanel.drwPanel.repaint();
                        }
                    } catch (InterruptedException ex) {
                        Logger.getLogger(RandomAction.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    Il problema e' che quando modifico il valore di pause, non succede nulla, non viene disegnato nulla e non si muove nulla.

  2. #2
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802
    Alcune considerazioni:

    1. la dicitura "extends Thread implements Runnable" è ridondante in quanto Thread implementa Runnable già di suo
    2.1 Il metodo sleep è statico e andrebbe chiamato staticamente: Thread.sleep(..) e non this.sleep(..). Non cambia nulla, è solo per chiarezza: sleep sospende il thread corrente, non l'oggetto su cui lo chiami (anche se possono coincidere).
    Ad esempio, se hai due Thread, t1 e t2, e da t1 fai t2.sleep(10000) il risultato non è quello che ti aspetti..!
    2.2 Il numero che passi a sleep() indica i MILLIsecondi

    Venendo al tuo problema, dovresti spiegare cos'è AutoPanel e come/dove disegni l'orologio.
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Animazione con Java

    Originariamente inviato da cryspolo
    Il problema e' che quando modifico il valore di pause, non succede nulla, non viene disegnato nulla e non si muove nulla.
    Un po' di questioni:

    1) Innanzitutto se pause è true il run va in ciclo continuo e velocissimo e consuma solo CPU. In tal senso sarebbe più opportuno un sistema "bloccante" con wait/notify.

    2) Se dall'esterno di RandomAction e soprattutto nel contesto di un altro thread vai ad accedere direttamente al campo 'pause', senza una apposita sincronizzazione non c'è alcuna garanzia che il thread che esegue il tuo run "veda" la modifica al campo.

    3) Per fare una cosa del genere, cioè un orologio, basterebbe anche più banalmente un semplice javax.swing.Timer, magari con un timing un po' più veloce (es. 1/10 secondo) per trovare meglio il momento di passaggio da un secondo all'altro.

    4) this.sleep(time) tecnicamente non è sbagliato. Ma sleep è un metodo statico di Thread. E visto che estendi Thread, almeno togli quel this che è "fuorviante".

    5) this.autoPanel.drwPanel.repaint();
    non è sbagliato tecnicamente (se ti funziona) ma accedi dall'esterno a quel campo drwPanel e in genere è il sintomo che il design delle classi fa un po' "acqua".
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Utente di HTML.it
    Registrato dal
    Jun 2011
    Messaggi
    43
    Grazie per i suggerimenti ora risistemo il codice e ve lo mostro.
    Immagino che esistano metodi migliori, il fatto e' che sto preparando un esame e mi sto attenendo alle direttive del docente, e tutti gli esempi di programmi con animazione sono fatti seguendo lo stesso principio che ho applicato anche io.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2011
    Messaggi
    43
    Ok, ho apportato delle modifiche al codice, e ora vi scrivo tutto.

    Questa e' la classe Time:

    codice:
    public class Time {
        DrawPanel drwPanel;
        int hours;
        int minutes;
        int seconds;
        
        public void haveTime() {                                    //Ottiene l'ora dal sistema
            Calendar c = new GregorianCalendar();
                        
            this.hours = c.get(Calendar.HOUR_OF_DAY);
            this.minutes = c.get(Calendar.MINUTE);
            this.seconds = c.get(Calendar.SECOND);
            
            this.drwPanel.repaint();
        }
        
        public void clearTime() {                          //Azzera l'orologio
            this.hours = 0;
            this.minutes = 0;
            this.seconds = 0;
        }
        
        public void setDrawPanel(DrawPanel drwPanel) {
            this.drwPanel = drwPanel;
        }
    }
    Questa e' la classe RandomAction:

    codice:
    public class RandomAction extends Thread {
        boolean pause = false;
        int time = 1000;
        int hours;
        int minutes;
        int seconds;
        Time t;
        
        public RandomAction(Time t) {
            this.t = t;
        }
        
        @Override
        public void run() {
            while(true) {
                
                    try {
                        if(pause) {
                            Thread.sleep(time);
                        
                            System.out.println("ciao");
                            
                            t.haveTime();
                        }
                    } catch (InterruptedException ex) {
                        Logger.getLogger(RandomAction.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    Questa e' la classe DrawPanel, che contiene la paintcomponent e che si occupa di calcolare la posizione delle lancette e di disegnarle, utilizzo settori circolari per disegnare le lancette, non perche' sono masochista, ma perche' la traccia d'esame lo richiede:

    codice:
    public class DrawPanel extends JPanel {
        Time t;
        String figure = "-";
        int X;
        int Y;
        int pointerh;
        int pointerm;
        int pointers;
        
        DrawPanel(Time t) {
            this.setTime(t);
            
            this.setVisible(true);
        }
        
        protected void setTime(Time t) {
            this.t = t;
        }
        
        protected void getCenter(int x, int y) {
            this.X = x/2;
            this.Y = y/2;
            
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            int width = getSize().width;
            int height = getSize().height;
            
            this.getCenter(width, height);
            
            g.setColor(Color.lightGray);
            g.fillRect(0, 0, width, height);     
            
            g.setColor(Color.black);
            g.drawLine(X - width, Y, X + width, Y);
            g.drawLine(X, Y - height, X, Y + height);
            
            if(this.figure == "Square") {
                g.setColor(Color.black);
                g.fillRect(X - 160, Y - 160, 320, 320);
                
                g.setColor(Color.lightGray);
                g.fillRect(X - 158, Y - 158, 316, 316); 
                
                g.setColor(Color.red);
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.seconds) * 6, 5);
                           
                g.setColor(Color.green);
                
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.minutes) * 6, 5);
                
                g.setColor(Color.blue);
                
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.hours) * 30, 5);
            }
            
            else if(this.figure == "Circle") {            
                g.setColor(Color.black);
                g.fillOval(X - 150, Y - 150, 300, 300);            
                
                g.setColor(Color.lightGray);
                g.fillOval(X - 148, Y - 148, 296, 296);          
                                   
                g.setColor(Color.red);
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.seconds) * 6, 5);
                            
                g.setColor(Color.green);
                
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.minutes) * 6, 5);
                           
                g.setColor(Color.blue);
                
                g.fillArc(X - 150, Y - 150, 300, 300, 87 - Math.abs(this.t.hours) * 30, 5);            
            }
        }
    }
    Infine questo e' l'AutoPanel, il pannello che si occupa di avviare il thread, ma che non capisco il perche' non funziona:

    codice:
    public class AutoPanel extends JPanel implements ActionListener {
        DrawPanel drwPanel;
        RandomAction th;
        Time t;
        JButton start;
        boolean doRandomAction = false;
        Panel myPanel;
        
        AutoPanel(Time t, DrawPanel drwPanel) {
            this.set(drwPanel, t);
    
            start = new JButton("Avvia");
            
            start.addActionListener(this);
            
            this.add(start);
            this.setVisible(false);
            
            th = new RandomAction(t);
            th.start();
        }
        
        public void set(DrawPanel drwPanel, Time t) {
            this.drwPanel = drwPanel; 
            this.t = t;
        }
    
        @Override
        public void actionPerformed(ActionEvent ae) {
            if(this.drwPanel.figure != "-") {
                this.th.pause = true;                              //qui e' dove modifico la variabile pause
                System.out.println(this.th.pause);
            }
            else JOptionPane.showMessageDialog(this, "Errore Selezione: \n"
                        + "Selezionare il tipo di quadrante per l'orologio");
            
        }
    }
    Quando metto la variabile pause = true, il thread non funziona, non si avvia nulla, e' come se nel ciclo while della classe RandomAction, non ci entrasse proprio.
    Perche'? Dove sbaglio?

    Da notare che se io metto pause = true dal codice e poi compilo ed eseguo, funziona tutto alla perfezione.

  6. #6
    Utente di HTML.it L'avatar di shane007
    Registrato dal
    Jun 2011
    residenza
    Trentino, tra vacche ed aria buona.
    Messaggi
    55
    Ahi ahi ahi... Occhio che l'esame è il 12 ed è sempre più vicino!

    Comunque questa è la mia soluzione a questo esame:

    https://www.dropbox.com/s/fagojor066...e_Orologio.rar

    PS: Ronchetti/Programmazione 2?

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da cryspolo
    Quando metto la variabile pause = true, il thread non funziona, non si avvia nulla, e' come se nel ciclo while della classe RandomAction, non ci entrasse proprio.
    Perche'? Dove sbaglio?
    Lo ripeto una seconda volta: senza una apposita "sincronizzazione" tra thread, non c'è alcuna garanzia che la modifica fatta a pause nel contesto del Event Dispatch Thread (in quel actionPerformed) sia "visibile" ad un altro thread (quello in cui è eseguito il run() di RandomAction).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.