Пожалуйста, исправьте меня, если я ошибаюсь, я думаю, это связано с тем, что поток Диспетчер событий останавливается, пока другой поток не завершит выполнение.
Это неправильно. Если другой поток действительно отключен от потока событий Swing, оба должны запускаться одновременно. У вас есть ошибка, когда:
- Вы думаете, что вы бежите от нити Качели событий, но вы не или
- Вы думаете, что вы обновляете GUI на 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-таймер, потому что нет никаких забот о вызове коды или выключить EDT, так как таймер гарантирует, что все вызовы будут в этой теме.
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());
}
}
Конечно, есть. Но без кода трудно сказать, где возникает проблема. – Paul
Попробуйте придумать [mcve]. Но, вероятно, вам просто нужно заглянуть в http://stackoverflow.com/questions/6567870/what-does-swingutilities-invokelater-do ... вы хотите вызвать SwingUtilties.invokeLater(), чтобы обновить эту метку от другой нить. И, конечно же, вы не хотите спать на EDT. – GhostCat
Если вы хотите работать с качелями и избегать кошмаров относительно обновлений пользовательского интерфейса, попробуйте использовать «SwingWorker». Эти потоки дополняются возможностями, которые позволяют выполнять подпольную задачу с возможностью обновления пользовательского интерфейса, не имея необходимости скрываться в нижней части потока диспетчеризации событий (событий Swing Framework). – Victor