Domanda

Sto realizzando un progetto e ho bisogno di una barra di avanzamento. Ho la lezione con il timer e funziona bene quando includo un principale; Ma quando provo a chiamarlo con il metodo Maingi, è tutto nero fino a quando non colpisce il 100%.

package microproject.resources;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Timer extends JFrame {

    JProgressBar current;
    JTextArea out;
    JButton find;
    Thread runner;
    int num = 0;
    int length = 0;

    public Timer() {
        setTitle("Progress");
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        length = Integer.parseInt(JOptionPane.showInputDialog(null, "How many seconds:"));

        JPanel p = new JPanel(new GridLayout(1,1));
        p.setPreferredSize(new Dimension(300,65));
        current = new JProgressBar(0, length);
        current.setPreferredSize(new Dimension(250,50));
        current.setValue(0);
        current.setStringPainted(true);
        p.add(current);
        setVisible(true);
        setContentPane(p);
        pack();
        setVisible(true);
        iterate();
    }

    public void iterate() {
        while(num < length +1) {
            current.setValue(num);
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {}
            num += 1;
        }

    }

    public static void main(String[] args) {
        Timer f = new Timer();
    }
}

Questo è il codice per la classe timer ^

package microproject.resources;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class GUIMain extends JFrame {

    public static void main(String []args){            
        GuiFrame();        
    }    

    public static void GuiFrame(){
        JFrame frame = new JFrame("Casino Royal3");
        frame.setSize(811,577);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

        frame.setLayout(new GridLayout(2,1));
        frame.setResizable(false);
        JPanel PNorth = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0));
        JPanel PSouth = new JPanel(new BorderLayout());


        //Creating Image for Casino Button
        ImageIcon img1 = new ImageIcon("src\\Casino.jpg");
        final JButton btn1 = new JButton(img1);
        btn1.setPreferredSize(new Dimension(550,274));
        btn1.setMargin(new Insets(0,0,0,0));
        PNorth.add(btn1, BorderLayout.EAST);
        btn1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                btn1.setIcon(new ImageIcon("src\\Casino2.jpg"));
            }
        });

        //Creating Image for Sheridan Label
        ImageIcon img2 = new ImageIcon("src\\SHERIDAN_LOGO.jpg");
        JButton btn2 = new JButton(img2);
        btn2.setMargin(new Insets(0,0,0,0));
        PNorth.add(btn2);
        btn2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ImageIcon instruc = new ImageIcon("src\\Instructions.jpg");
                JLabel instructions = new JLabel(instruc);
                JOptionPane.showConfirmDialog(null, instructions, "instructions", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE);
            }
        });

        JPanel timmus = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0));
        timmus.setPreferredSize(new Dimension(166, 273));
        timmus.setBackground(Color.BLUE);

        ImageIcon time = new ImageIcon("src\\Timer.jpg");
        JButton timer = new JButton(time);
        timer.setMargin(new Insets(0,0,0,0));
        timer.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Timer f = new Timer();
            }
        });
        timmus.add(timer);

        ImageIcon mus = new ImageIcon("src\\music.jpg");
        JButton music = new JButton(mus);
        music.setMargin(new Insets(0,0,0,0));
        timmus.add(music);

        JPanel games = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0));
        games.setPreferredSize(new Dimension(500,279));
        games.setBackground(Color.BLUE);

        ImageIcon calculator = new ImageIcon("src\\Calculator.jpg");
        JButton calc = new JButton(calculator);
        calc.setMargin(new Insets(0,0,0,0));
        calc.setPreferredSize(new Dimension(166,273));
        games.add(calc);
        calc.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Calculator c1 = new Calculator();
            }
        });

        ImageIcon g1 = new ImageIcon("src\\250Hangman.jpg");
        JButton game1 = new JButton(g1);
        //game1.setBackground(Color.WHITE);
        game1.setMargin(new Insets(0,0,0,0));
        game1.setPreferredSize(new Dimension(166,273));
        games.add(game1);
        game1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Hangman h1 = new Hangman();
            }
        });


        ImageIcon g2 = new ImageIcon("src\\Minesweeper.jpg");
        JButton game2 = new JButton(g2);
    //    game2.setBackground(Color.WHITE);
        game2.setMargin(new Insets(0,0,0,0));    
        game2.setPreferredSize(new Dimension(166,273));
        games.add(game2);

        PSouth.add(timmus, BorderLayout.CENTER);
        PSouth.add(games, BorderLayout.EAST);

        frame.add(PNorth, BorderLayout.NORTH);
        frame.add(PSouth, BorderLayout.SOUTH);

        frame.setVisible(true);
        frame.pack();
    }
}

Questo è l'intero programma, Timer ActionListener si chiama "timer"

Grazie in anticipo

È stato utile?

Soluzione

Benvenuto nel meraviglioso mondo del thread di spedizione di eventi bloccato (e violazione del thread iniziale)

Fondamentalmente, Swing è un singolo ambiente thread, tutti gli aggiornamenti e le modifiche all'interfaccia utente dovrebbero essere eseguiti nel contesto del thread di eventi (aka EDT).

L'EDT è responsabile, tra le altre cose, di elaborare richieste di riduzione. Se, per qualche motivo, blocchi questo thread (ad esempio, usando un ciclo di lunga durata o bloccando IO), impedirà all'EDT di elaborare nuove richieste di verniciatura, facendo sembrare che il tuo programma fosse appeso ... perché essenzialmente lo ha.

Il motivo per cui potresti vedere una differenza tra la corsa Timer Direttamente e usarlo nella tua GUI è perché quando l'applicazione sarà avviata, sarà in esecuzione all'interno, ciò che è comunemente noto come il thread "principale".

Quando si crea per la prima volta un contenitore di altalena di alto livello, l'EDT viene avviato (che è un thread separato), il che significa che l'interfaccia utente apparirà nel proprio thread, ma l'applicazione continuerà a funzionare nel thread "principale", permettendo il tuo iterate Metodo da eseguire indipendentemente dall'EDT.

Tuttavia, quando provi a eseguirlo dalla tua GUI, è tutto in esecuzione nel contesto dell'EDT, causando il blocco.

Inizia dando un'occhiata

Per risolvere il problema, in base al tuo codice di esempio, suggerirei di usare un SwingWorker. Ciò ti consentirà di eseguire la tua "attività di lunga durata" in un thread di fondo, ma fornisce una serie di metodi che ti consentono di risincronizzare gli aggiornamenti all'EDT. Questo è molto importante, poiché non dovresti mai tentare di aggiornare l'interfaccia utente o modificare il suo stato da qualsiasi thread oltre all'EDT.

Date un'occhiata al Discussioni del lavoratore e swelayer per ulteriori dettagli

E se necessario, alcuni esempi ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top