JprogressBar come può avanzare

di il
6 risposte

JprogressBar come può avanzare

Salve ragazzi ho implementato una jprogressBar nel mio programma ma guardando in giro credo di aver capito che non esistono funzioni che tipo fanno avanzare la barra di progresso ogni tot millisecondi giusto?? non mi è ben chiaro quindi come fare avevo pensato tipo un ciclo for che avanza e ogni volta faccio stampare la nuova percentuale è la migliore soluzione?

6 Risposte

  • Re: JprogressBar come può avanzare

    broke31 ha scritto:


    guardando in giro credo di aver capito che non esistono funzioni che tipo fanno avanzare la barra di progresso ogni tot millisecondi giusto??
    Non è che non esistono .... sei tu che puoi/devi "aggiornare" il value del JProgressBar ogni tot di tempo o eventualmente in base al "progresso" di qualche altra operazione (es. di I/O).

    broke31 ha scritto:


    avevo pensato tipo un ciclo for che avanza e ogni volta faccio stampare la nuova percentuale è la migliore soluzione?
    Il punto è: in quale contesto, ovvero in quale thread. Esiste un principio fondamentale in Swing: esiste un unico thread, il EDT (Event Dispatch Thread) che si occupa di disegnare la interfaccia utente e di dispacciare gli eventi. Salvo casi particolari (e documentati), l'accesso alla interfaccia utente (setText, setValue, getDocument ecc.... qualunque altro che non sia documentato come thread-safe) va fatto solo nel contesto del EDT.

    Quindi se pensavi es. nel actionPerformed (per un pulsante) di fare un ciclo for in cui usi setValue sul JProgressBar e fai un Thread.sleep .... no, è sbagliato. Non vedresti alcun aggiornamento, se non alla fine di tutto!
  • Re: JprogressBar come può avanzare

    Non ho ben capito la tua risposta scusa... il fatto del ciclo for l'ho infatti testato solo diciamo per " commettere l'errore da te detto" in modo da imparare quindi la soluzione è quella di dover creare un nuovo therd nel mio programma?
  • Re: JprogressBar come può avanzare

    broke31 ha scritto:


    quindi la soluzione è quella di dover creare un nuovo therd nel mio programma?
    Allora: se devi fare cose relativamente "brevi" ma temporizzate ogni tot di tempo, una soluzione è usare javax.swing.Timer.
    Se invece devi eseguire un lavoro potenzialmente molto lungo e che utilizza computazioni "pesanti" oppure I/O "bloccante", la soluzione è naturalmente la creazione di un thread a parte. Questo per evitare di tenere appunto "impegnato" il EDT. Perché se lo tieni tu impegnato con tuoi lavori, è chiaro che il controllo non torna subito al framework e quindi non possono essere aggiornati i componenti Swing, né dispacciati altri eventi! Questo mi pare che lo hai già chiaro.

    Creare un nuovo thread è però solo una parte della soluzione ed è invece fonte di altre questioni. Se sei nel contesto di un tuo thread, non devi fare direttamente:

    progrBar.setValue( .... );

    Sono poche (davvero poche) le operazioni sulla interfaccia utente che sono documentate come "thread-safe", ovvero fattibili da qualunque thread (anche non il EDT). E setValue di JProgressBar non è tra queste.
    Quindi in questo caso dovresti "far passare" la esecuzione di solo questo setValue nel EDT e per questo esistono i ben noti invokeLater/invokeAndWait di SwingUtilities.

    Quindi in tuo thread la soluzione per aggiornare una progress bar dovrebbe essere:
    //..... tuo lavoro .....
    
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            progrBar.setValue( ...... );
        }
    });
    
    //..... tuo lavoro .....
    E comunque se usi il multi-threading devi avere anche ben chiari i concetti di sincronizzazione, mutua-esclusione, "visibilità" delle modifiche e altro.
  • Re: JprogressBar come può avanzare

    Grazie per i preziosi consigli, ci sto provando ancora usando il multi treding ma senza venirne a capo, la programmazione a multitreding l'ho fatta in C l'anno scorso... in JAVA mai, quindi credo proprio che sarà molto più dura del previsto... il tuo codice l'ho modificato in questo modo:
    
    SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				JProgressBar progrBar= new JProgressBar();
    
    				
    				{frame.setVisible(true);
    				
    				progrBar.setValue(progrBar.getValue()+1 );
    				aspetta(5000); // funzione che aspetta 5 secondi 
    				frame.repaint();
    
    				}
    
    			}
    		});
    	}
    
    
    
    ma nulla il frame sembra rimane bianco
    edit: sono quasi riuscito ad avere un risultato decente, adesso il frame con il caricamento viene visualizzato la barra parte da 0 ed ad un certo punto passa direttamente a 100... vorrei però farlo in modo graduale... posso postarti il codice per un tuo sguardo se non crea troppo disturbo?
  • Re: JprogressBar come può avanzare

    Ecco un semplice esempio:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class ProgressBarUpdate {
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new ProgressBarUpdateFrame().setVisible(true);
                }
            });
        }
    }
    
    class ProgressBarUpdateFrame extends JFrame {
        private JProgressBar progressBar;
        private JButton startButton;
        private Thread thread;
    
        public ProgressBarUpdateFrame() {
            super("ProgressBar Update");
    
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setSize(300, 200);
    
            progressBar = new JProgressBar(0, 100);
            startButton = new JButton("Start");
    
            getContentPane().add(progressBar, BorderLayout.NORTH);
            getContentPane().add(startButton, BorderLayout.SOUTH);
    
            startButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (thread != null && thread.isAlive()) {
                        JOptionPane.showMessageDialog(null, "Thread attivo!");
                    } else {
                        thread = new Thread(new UpdateRunnable());
                        thread.start();
                    }
                }
            });
        }
    
        private class UpdateRunnable implements Runnable {
            public void run() {
                try {
                    for (int i = 1; i <= 100; i++) {
                        Thread.sleep(100);   // 100 ms
    
                        final int val = i;
    
                        SwingUtilities.invokeLater(new Runnable() {
                            public void run() {
                                progressBar.setValue(val);
                            }
                        });
                    }
                } catch (InterruptedException e) {
                    System.err.println(e);
                }
            }
        }
    }
  • Re: JprogressBar come può avanzare

    Mille grazie, ho preso il tuo codice l'ho capito e l'ho riadattato al mio problema, funziona tutto alla perfezione! grazie
Devi accedere o registrarti per scrivere nel forum
6 risposte