我正在制作一个项目,需要一个进度栏。我有与计时器的课程,当我包括主机时运行良好;但是,当我尝试以Maingui方法称呼它时,它是黑色的,直到它达到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();
    }
}

这是计时器类的代码 ^

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();
    }
}

这就是整个程序,计时器ActionListener称为“计时器”

提前致谢

有帮助吗?

解决方案

欢迎来到封锁事件派遣线程的美好世界(违反初始线程)

基本上,Swing是一个单个螺纹环境,预计将在事件调度线程(又称EDT)的上下文中执行所有更新和对UI的修改。

EDT负责处理重新粉刷请求。如果出于某种原因,您可以阻止此线程(例如,使用长期运行循环或阻止IO),它将阻止EDT处理新的油漆请求,从而使其看起来好像您的程序已悬挂...因为本质上是它有。

您可能会看到运行之间有区别的原因 Timer 直接在GUI中使用它是因为当启动应用程序时,它将在内部运行,通常称为“主”线程。

当您首先创建一个顶级秋千容器时,EDT启动(这是一个单独的线程),这意味着UI将出现在其自己的线程中,但是应用程序将继续在“主”线程中运行,允许您 iterate 独立于EDT运行的方法。

但是,当您尝试从GUI内运行它时,所有这些都在EDT的上下文中运行,从而使其被阻止。

首先看一下

为了根据您的示例代码来解决问题,我建议使用 SwingWorker. 。这将使您可以在背景线程中运行“长期运行任务”,但是提供了许多方法,使您可以将更新重新回到EDT。这非常重要,因为您绝对不应该尝试更新UI或从EDT的其他线程更改其状态。

看一眼 工人线和摇摆工人 更多细节

如果需要,一些例子...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top