我正在制作一个项目,需要一个进度条。我有定时器的课程,当我包含一个主要时,它运行正常;但是当我尝试在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();
}
}
这是Timer Class的代码^
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被称为“计时器”
提前致谢
答案 0 :(得分:3)
欢迎来到被阻止的事件调度线程的奇妙世界(并且违反了初始线程)
基本上,Swing是一个单线程环境,对UI的所有更新和修改都应该在事件调度线程(AKA EDT)的上下文中执行。
除其他事项外,EDT负责处理重绘请求。如果由于某种原因,你阻止这个线程(例如,使用一个长期运行的循环或阻塞IO),它会阻止从美国东部时间处理新漆的要求,使得它看起来好像你的程序已经暂停...因为它本质上具有您可能会看到Timer
直接运行在你的GUI使用它之间的差异的原因是因为当应用程序启动时,它会内运行,什么是俗称的“主”线程。
当您第一次创建顶级Swing容器时,启动EDT(这是一个单独的线程),这意味着UI将出现在它自己的线程中,但应用程序将继续在“主”线程中运行,允许您的iterate
方法独立于EDT运行。
但是,当您尝试在GUI中运行它时,它们都在EDT的上下文中运行,导致它被阻止。
首先看看
要解决此问题,请根据您的示例代码建议使用SwingWorker
。这将允许您在后台线程中运行“长时间运行的任务”,但提供了许多方法,允许您将更新重新同步回EDT。这非常重要,因为您永远不应该尝试更新UI或从EDT以外的任何线程更改它的状态。
请查看Worker Threads and SwingWorker了解详情
如果需要,还有一些例子......