Java:即使 SwingUtilities.invokeLater,线程也不会修改 GUI
Java: A Thread don't modify the GUI even with SwingUtilities.invokeLater
我对这段代码有疑问:
public class Gui_01 extends JFrame {
private JPanel display;
private ActionListener visualizza() {
ActionListener evento = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
display.removeAll();
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
);
t.start();
}
};
return evento;
}
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
}
});
}}
我不明白为什么代码不能正常工作,thread t 和 updateProgress 中的线程工作正常,但是任何修改显示不会影响 GUI,即使使用 invokeLater。
display.add(visualizza, BorderLayout.SOUTH)
此代码不修改 gui,我知道这是正常的(由于 Swing),但为什么 invokeLater 不起作用。
抱歉我的英语不好,提前感谢您的回复。
首先删除线程中的 display.add(visualizza, BorderLayout.SOUTH);
语句。因为你不应该从 EDT 上下文之外更新或修改 UI...
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
//display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
事实上,我不鼓励您在 EDT 之外创建 UI 元素,因为您无法保证它们何时会开始与 UI.
交互
其次,在更新 UI...
后调用 revalidate
和 repaint
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
display.revalidate();
display.repaint();
}
});
}}
Swing 在更新 UI 时是懒惰的,这是一件好事,因为它允许您进行彻底的更改,并且仅在您准备好时才更新 UI所以。
我还鼓励您改用 SwingWorker
,因为它具有可用于将更新与 EDT 同步的功能。有关详细信息,请参阅 Worker Threads and SwingWorker
我对这段代码有疑问:
public class Gui_01 extends JFrame {
private JPanel display;
private ActionListener visualizza() {
ActionListener evento = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
display.removeAll();
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
);
t.start();
}
};
return evento;
}
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
}
});
}}
我不明白为什么代码不能正常工作,thread t 和 updateProgress 中的线程工作正常,但是任何修改显示不会影响 GUI,即使使用 invokeLater。
display.add(visualizza, BorderLayout.SOUTH)
此代码不修改 gui,我知道这是正常的(由于 Swing),但为什么 invokeLater 不起作用。
抱歉我的英语不好,提前感谢您的回复。
首先删除线程中的 display.add(visualizza, BorderLayout.SOUTH);
语句。因为你不应该从 EDT 上下文之外更新或修改 UI...
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
//display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
事实上,我不鼓励您在 EDT 之外创建 UI 元素,因为您无法保证它们何时会开始与 UI.
交互其次,在更新 UI...
后调用revalidate
和 repaint
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
display.revalidate();
display.repaint();
}
});
}}
Swing 在更新 UI 时是懒惰的,这是一件好事,因为它允许您进行彻底的更改,并且仅在您准备好时才更新 UI所以。
我还鼓励您改用 SwingWorker
,因为它具有可用于将更新与 EDT 同步的功能。有关详细信息,请参阅 Worker Threads and SwingWorker