有没有办法从单独的线程中连续更新循环内的JLabel。现在,只有循环结束后,Jlabel才会更新。
如果错误,请纠正我,我认为这是因为事件调度程序线程暂停,直到另一个线程完成执行。
有什么办法可以同时运行两个线程吗?
我尝试在循环中给出一个Thread.sleep(300)但是没有用。
答案 0 :(得分:4)
如果错误,请纠正我,我认为这是因为事件调度程序线程暂停,直到另一个线程完成执行。
这是错误的。如果另一个线程真正在Swing事件线程中运行,则两个线程应该同时运行。你有一个错误:
最重要的是,您在代码中未显示错误,为了获得更好的答案,请显示相关代码。
如,
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
@SuppressWarnings("serial")
public class UpdateLabel extends JPanel {
// label to update
private JLabel statusLabel = new JLabel("");
public UpdateLabel() {
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3));
topPanel.add(new JLabel("Counter:"));
topPanel.add(statusLabel);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new StartThreadAction("Start Thread")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.PAGE_END);
}
// fail safe method that is guaranteed to add text to the label
// **on the Swing event thread**
public void setLabelText(final String text) {
if (SwingUtilities.isEventDispatchThread()) {
statusLabel.setText(text);
} else {
SwingUtilities.invokeLater(() -> {
statusLabel.setText(text);
});
}
}
// Abstract Action for our JButton
private class StartThreadAction extends AbstractAction {
protected static final int MAX_COUNT = 10;
protected static final long SLEEP_TIME = 1;
public StartThreadAction(String name) {
super(name);
}
@Override
public void actionPerformed(ActionEvent e) {
// start a new thread
new Thread(new Runnable() {
private int counter = 0;
@Override
public void run() {
// within the background thread update a counter and sleep
while (counter < MAX_COUNT) {
String text = "" + counter;
setLabelText(text); // call our fail safe method
counter++;
try {
// sleep for 1 second
TimeUnit.SECONDS.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// rare time it's OK to leave this blank
}
}
}
}).start();
}
}
private static void createAndShowGui() {
UpdateLabel mainPanel = new UpdateLabel();
JFrame frame = new JFrame("UpdateLabel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start GUI on the Swing event thread
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
说完这一切之后,对于像延迟的简单计数这样的事情,我会使用Swing Timer,因为不用担心在EDT上打开或关闭代码,因为Timer保证所有的调用将在这个主题上。
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class UpdateLabel2 extends JPanel {
// label to update
private JLabel statusLabel = new JLabel("");
private Timer timer;
public UpdateLabel2() {
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3));
topPanel.add(new JLabel("Counter:"));
topPanel.add(statusLabel);
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new StartTimerAction("Start Timer")));
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(bottomPanel, BorderLayout.PAGE_END);
}
// Abstract Action for our JButton
private class StartTimerAction extends AbstractAction {
protected static final int MAX_COUNT = 10;
private static final int TIMER_DELAY = 1000; // 1 second
private int counter = 0;
public StartTimerAction(String name) {
super(name);
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
@Override
public void actionPerformed(ActionEvent e) {
if (timer != null && timer.isRunning()) {
return; // wait until timer finishes
}
timer = new Timer(TIMER_DELAY, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e2) {
if (counter >= MAX_COUNT) {
timer.stop();
counter = 0;
} else {
counter++;
statusLabel.setText("" + counter);
}
}
});
timer.start();
}
}
private static void createAndShowGui() {
UpdateLabel2 mainPanel = new UpdateLabel2();
JFrame frame = new JFrame("UpdateLabel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// start GUI on the Swing event thread
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}