我正在阅读 Thinking in Java,作者强调 main 方法不应该调用 swing 方法。作为该实践的示例,他展示了以下代码片段(可在他的网页上找到):
//: gui/SubmitSwingProgram.java
import javax.swing.*;
import java.util.concurrent.*;
public class SubmitSwingProgram extends JFrame {
JLabel label;
public SubmitSwingProgram() {
super("Hello Swing");
label = new JLabel("A Label");
add(label);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
setVisible(true);
}
static SubmitSwingProgram ssp;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() { ssp = new SubmitSwingProgram(); }
});
TimeUnit.SECONDS.sleep(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ssp.label.setText("Hey! This is Different!");
}
});
}
} ///:~
然后通过 invokeLater 方法创建和初始化 gui 对象,使其成为线程安全的。但是几页之后,作者给出了以下代码:
//: gui/Button2.java
// Responding to button presses.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import static net.mindview.util.SwingConsole.*;
public class Button2 extends JFrame {
private JButton
b1 = new JButton("Button 1"),
b2 = new JButton("Button 2");
private JTextField txt = new JTextField(10);
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String name = ((JButton)e.getSource()).getText();
txt.setText(name);
}
}
private ButtonListener bl = new ButtonListener();
public Button2() {
b1.addActionListener(bl);
b2.addActionListener(bl);
setLayout(new FlowLayout());
add(b1);
add(b2);
add(txt);
}
public static void main(String[] args) {
run(new Button2(), 200, 150);
}
} ///:~
SwingConsole 在哪里:
//: net/mindview/util/SwingConsole.java
// Tool for running Swing demos from the
// console, both applets and JFrames.
package net.mindview.util;
import javax.swing.*;
public class SwingConsole {
public static void
run(final JFrame f, final int width, final int height) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
}
} ///:~
因此与前面的示例相反,在主方法/主线程中创建并初始化实现 JFrame 的对象。
那么我的问题是: (1) 第二个例子是错误的还是第一个被夸大了? (2) 仅在 setVisible 调用之后和该语句之前通过 invokeLater 调用 swing 方法是否足够,在主线程中调用 swing 方法是安全的?
最佳答案
第二个例子是错误的。必须从事件分派(dispatch)线程创建和使用 Swing 组件。参见 https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html .
引自 the javadoc :
Calls to an application's main method, or methods in Applet, are not invoked on the event dispatching thread. As such, care must be taken to transfer control to the event dispatching thread when constructing and showing an application or applet.
(强调我的)
关于java - 如何在 java swing 中以线程安全的方式初始化 gui 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26834078/