#java #swing #jframe #event-dispatch-thread
#java #качать #jframe #событие-отправка-поток
Вопрос:
Я пытаюсь создать JFrame
и увидеть ход работы счетчика.
int i = 1;
while (i < 100000){
textField.setText(String.valueOf(i));
System.out.println(i);
i ;
}
Когда я запускаю его, я вижу прогресс на консоли, но значение textField
не меняется. Он изменяется на 100000, когда цикл заканчивается.
Как я могу заставить его показывать прогресс, как в консоли?
Ответ №1:
Существует ряд важных различий между и другими инструментами графического интерфейса, такими как C #.
Во-первых, компоненты Swing ИМЕЮТ общий собственный одноранговый узел. Во многих других графических интерфейсах компоненты имеют свой собственный одноранговый узел, это влияет на контекст, в котором вы можете получить доступ к этим компонентам.
Во-вторых, поскольку компоненты Swing имеют общий собственный одноранговый узел, они по своей сути не являются потокобезопасными (например, все они используют одну и ту же очередь сообщений), это означает, что вы никогда не должны изменять компонент пользовательского интерфейса вне контекста потока отправки событий.
В-третьих, вы никогда не должны блокировать поток отправки событий, это помешает ему обрабатывать новые события, включая запросы на рисование.
В этом контексте вам, вероятно, следует использовать sa javax.swing.Timer
, который позволит вам запланировать обратный вызов (который будет выполняться в контексте EDT) через регулярные промежутки времени, что делает его безопасным для использования, например, в контексте Swing framework…
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Counter {
public static void main(String[] args) {
new Counter();
}
public Counter() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JLabel label;
private Timer timer;
private int count;
public TestPane() {
label = new JLabel("...");
setLayout(new GridBagLayout());
add(label);
timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
count ;
if (count < 100000) {
label.setText(Integer.toString(count));
} else {
((Timer)(e.getSource())).stop();
}
}
});
timer.setInitialDelay(0);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
Взгляните на параллелизм в Swing и как использовать таймеры Swing для получения более подробной информации…