java - 如果 while 循环为空,Swing 程序不会关闭,但是如果 while 循环包含 print 则关闭
问题描述
在尝试使用 swing(类似于 JOptionPane)创建一个小对话框 API 时,我遇到了一个非常奇怪的“错误”。
基本上你调用一个打开JFrame的方法,等到一个按钮被选中并返回它;等到一个按钮被选中,我使用了一个 while 循环:while (isVisible()) {}
。现在奇怪的部分是如果循环是空的(因为它在这里),程序将不会完成,但是如果我将 aSystem.out.print()
放在里面它会。我试图在里面放一些别的东西(比如int i = 0;
),但这并没有什么不同。
编辑:即使没有打印和断点,使用调试器也可以解决这个问题。
由于我不知道问题可能是什么,我将发布整个Dialog
课程:
package Frame.Dialogs;
import GameEngine.EngineMgr;
import javax.swing.*;
import java.awt.*;
public class Dialog extends JFrame {
public enum Buttons {
OK(Dialog.OK),
YES(Dialog.YES),
RETURN(Dialog.RETURN),
CONFIRM(Dialog.CONFIRM),
YES_NO(Dialog.YES, Dialog.NO),
YES_NO_CANCEL(Dialog.YES, Dialog.NO, Dialog.CANCEL),
YES_CANCEL(Dialog.YES, Dialog.CANCEL),
YES_RETURN(Dialog.YES, Dialog.RETURN),
OK_CANCEL(Dialog.OK, Dialog.CANCEL),
CONFIRM_CANCEL(Dialog.CONFIRM, Dialog.CANCEL),
CONFIRM_RETURN(Dialog.CONFIRM, Dialog.RETURN);
private JButton[] buttons;
Buttons(JButton... buttons) {
this.buttons = buttons;
}
JButton[] val() {
return buttons;
}
}
public static final JButton OK = new JButton("OK");
public static final JButton NO = new JButton("NO");
public static final JButton YES = new JButton("YES");
public static final JButton CANCEL = new JButton("CANCEL");
public static final JButton RETURN = new JButton("RETURN");
public static final JButton CONFIRM = new JButton("CONFIRM");
private static boolean initialized = false;
private JPanel button;
private JPanel content;
private JButton selection;
private Dialog(JPanel panel, String title, Buttons buttons) {
if (!initialized)
initialize();
setTitle(title);
setIconImage(null);
button = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
for (JButton b : buttons.val())
button.add(b);
content = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
content.add(panel);
}
@SuppressWarnings("StatementWithEmptyBody")
private JButton display() {
setLayout(new GridBagLayout());
setBackground(Color.BLACK);
GridBagConstraints c1 = new GridBagConstraints();
c1.fill = GridBagConstraints.BOTH;
c1.gridx = 0;
c1.gridy = 0;
c1.insets = new Insets(10, 10, 10, 10);
GridBagConstraints c2 = (GridBagConstraints) c1.clone();
c2.gridy = 1;
add(content, c1);
add(button, c2);
pack();
Dimension sc = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((sc.width - getWidth()) / 2, (sc.height - getHeight()) / 2);
setVisible(true);
//Strange loop
//Will get stuck:
//while (isVisible()) {}
//Works fine:
while (isVisible())
System.out.print("");
return selection;
}
private void initialize() {
//JButton[] buttons = new JButton[]{YES, NO, OK, CANCEL, RETURN, CONFIRM};
JButton[] buttons = new JButton[]{OK};
for (JButton b : buttons) {
b.setBorder(BorderFactory.createEmptyBorder());
b.setContentAreaFilled(false);
b.setIcon(new ImageIcon(EngineMgr.getGraphicEngine().get("bt_" + b.getText()).getScaledInstance(150, 84, Image.SCALE_SMOOTH)));
b.setSelectedIcon(new ImageIcon(EngineMgr.getGraphicEngine().get("sBt_" + b.getText()).getScaledInstance(150, 84, Image.SCALE_SMOOTH)));
b.setPressedIcon(new ImageIcon(EngineMgr.getGraphicEngine().get("pBt_" + b.getText()).getScaledInstance(150, 84, Image.SCALE_SMOOTH)));
b.setText("");
b.setSize(new Dimension(150, 50));
b.addActionListener(e -> {
selection = b;
dispose();
});
}
}
public static JButton showDialog(String msg, String title, Buttons buttons) {
JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
panel.add(new JLabel(msg));
return new Dialog(panel, title, buttons).display();
}
public static JButton showDialog(JPanel panel, String title, Buttons buttons) {
return new Dialog(panel, title, buttons).display();
}
}
还有这里的电话:
JButton selection = Dialog.showDialog("Test 1", "Test", Dialog.Buttons.OK);
if (selection == Dialog.OK)
System.out.println("OK");
System.exit(0);
解决方案
几乎可以肯定,while
循环在 AWT 事件调度线程 (EDT) 之外运行。用于java.awt.EventQueue.invokeLater
获得正确的线程。
如果您确实将 Swing/AWT 与多个线程一起使用(EDT 将是一个线程 - 所以甚至不要使用主线程),那么您将遇到竞争条件并且会发生奇怪的事情。System.out.println
即使使用单线程硬件,也会导致一些延迟,从而导致激烈的行为发生变化,这是很常见的。
在 EDT 上,阻塞或运行繁忙的循环会导致 UI 冻结。因此,您将需要一个 AWT/Swing 事件处理程序来将事件发送回您拥有的任何其他线程,或者启动一个新任务。
推荐阅读
- java - java Querydsl 错误结果与 or()
- azure - Open ID 连接以使用 Azure AD AADSTS90019 错误进行身份验证
- apache-kafka - Kafka主题在创建后无法分配领导者
- java - MouseInfo 返回不适用于 Robot 类的坐标
- html - 是否可以将我的页脚固定在中心并且文本继续以不同的颜色闪烁
- r - R sommer 包 - 版本过期消息
- ruby-on-rails - Bootstrap 模态插件无法正常工作
- python - 如何将特殊字符传递到 Flask 中的 url
- php - PHP POST请求 - 无法获取第一行MYSQL
- django - 如何从 Django 多对多关系中获取数据?