【问题标题】:JProgressBar - Won't work in the class that I am calling it inJProgressBar - 在我调用它的类中不起作用
【发布时间】:2013-11-06 23:30:04
【问题描述】:

我正在制作一个项目,需要一个进度条。我有 Timer 的课程,当我包含一个 main 时它运行良好;但是当我尝试在 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();
    }
}

这就是整个程序,Timer ActionListener被称为“定时器”

提前致谢

【问题讨论】:

  • 您的迭代方法正在停止 EDT...

标签: java swing user-interface event-dispatch-thread jprogressbar


【解决方案1】:

欢迎来到阻塞事件调度线程(以及违反初始线程)的奇妙世界

基本上,Swing 是一个单线程环境,对 UI 的所有更新和修改都应在事件调度线程 (AKA EDT) 的上下文中执行。

除其他外,EDT 负责处理重绘请求。如果由于某种原因阻塞了这个线程(例如,使用一个长时间运行的循环或阻塞 IO),它将阻止 EDT 处理新的绘制请求,使它看起来好像你的程序已经挂起......因为本质上它有。

您可能会发现直接运行 Timer 和在 GUI 中使用它之间存在差异的原因是,当应用程序启动时,它将在通常称为“主”线程的内部运行。

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

但是,当您尝试从 GUI 中运行它时,它都在 EDT 的上下文中运行,导致它被阻止。

先看看

要解决此问题,根据您的示例代码,我建议使用SwingWorker。这将允许您在后台线程中运行“长时间运行的任务”,但提供了许多允许您将更新重新同步回 EDT 的方法。这一点非常重要,因为您不应该尝试从除 EDT 之外的任何线程更新 UI 或更改其状态。

查看Worker Threads and SwingWorker了解更多详情

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

【讨论】:

  • 我一直在阅读这方面的内容,这一切都很有道理,但我的教授没有提到 EDT 或 SwingWorker,只是想知道他们是否有某种做同样事情的方式使用 Threads,因为这是他在课堂上提到的。
  • 是的,基本上,SwingWorker 是一个自容器线程工厂;)。你可以创建一个Thread,但是你需要使用SwingUtilities.invokeLater(new Runnable() {...});重新同步回EDT
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-31
  • 2012-03-06
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-25
相关资源
最近更新 更多