当扫描仪等待用户输入时,java GUI冻结
我意识到,您需要使用事件调度线程来避免冻结和死锁,但现在我来讨论冻结问题。我怀疑我有这个问题是因为封装的EDT
这是一个包含主要静态方法的类:
@SuppressWarnings("serial")
public class WelcomeScreen extends JFrame implements ActionListener {
/*
* initialize variables
*/
private JButton btnSubmit;
private JTextField nameInput;
private JLabel enterName;
public WelcomeScreen() {
/*
* build the welcome frame with all components
*/
setAlwaysOnTop(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setBounds(0, 0, 514, 256);
getContentPane().setLayout(null);
// welcome label
JLabel label_welcome = new JLabel("<html>Welcome to <br/>Game</html>");
label_welcome.setHorizontalAlignment(SwingConstants.CENTER);
label_welcome.setBounds(159, 11, 190, 32);
getContentPane().add(label_welcome);
// create the warrior button
btnSubmit = new JButton("Start");
btnSubmit.setBounds(209, 129, 89, 23);
btnSubmit.addActionListener(this);
btnSubmit.setFocusable(false);
getContentPane().add(btnSubmit);
enterName = new JLabel("Enter Player Name:");
enterName.setBounds(50, 60, 150, 50);
getContentPane().add(enterName);
nameInput = new JTextField();
nameInput.setBounds(212, 70, 125, 25);
getContentPane().add(nameInput);
// set frame visible
setVisible(true);
}
/*
* action listener
*/
public void actionPerformed(ActionEvent evt) {
if (evt.getSource().equals(btnSubmit)) {
dispose();
new Core();
}
}
/*
* <<<<<MAIN STATIC METHOD>>>>>
*/
public static void main(String[] args) {
// safely start the welcome frame
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new WelcomeScreen();
}
});
}
}
这是扩展JFrame的第二个类。这是冻结的GUI。如果查看gameEngine()方法,您会注意到字符串输入=键盘。next(),导致冰冻。如果这一行被注释掉,GUI将显示两个字符串“test1”和“test2”
@SuppressWarnings("serial")
public class Core extends JFrame {
/*
* initialize variables
*/
private Scanner keyboard;
private JTextArea textArea;
public Core() {
/*
* create the frame that displays output messages
*/
setBounds(0, 0, 800, 400);
setResizable(false);
setLocationRelativeTo(null);
setAlwaysOnTop(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setLayout(null);
JPanel panel = new JPanel();
panel.setBounds(10, 11, 774, 349);
panel.setLayout(null);
getContentPane().add(panel);
textArea = new JTextArea();
JScrollPane scroll = new JScrollPane(textArea);
scroll.setBounds(0, 0, 774, 349);
textArea.setBounds(10, 11, 443, 279);
panel.add(scroll);
// THIS ISN'T EVEN SHOWING UP
appendMessage("test1");
// set frame visible
setVisible(true);
// NEITHER IS THIS
appendMessage("test2");
/*
* start game engine
*/
gameEngine();
}
/*
* start gameEngine
*/
public void gameEngine() {
// instantiate scanner
keyboard = new Scanner(System.in);
// <<<<<<<<<<<<<<<THIS HERE IS CAUSING THE GUI TO FREEZE>>>>>>>>>>>>>>>
String input = keyboard.next();
}
// append a message to the GUI
public void appendMessage(String s) {
textArea.append("> " + s + "\n");
}
}
# 1 楼答案
您的问题是,扫描仪正在阻止Swing事件线程,从而阻止GUI绘制和与用户交互。一个简单的解决方案是在后台线程中进行扫描仪交互。更好的解决方案是完全摆脱扫描仪(System.in),通过GUI实现所有用户交互。控制台I/O和GUI I/O不应混合使用
使用JTextField和布局管理器获取并响应输入的一个简单示例:
# 2 楼答案
使用一个
JTextField
作为输入,再加上一个ActionListener
,您可以对适当的事件做出响应,比如输入键使用
JTextArea
作为输出查看How to Use Text Fields、How to Use Text Areas、How to Write an Action Listeners和Writing Event Listeners了解更多详细信息
你可能还想看看Model-View-Controller,这将帮助你保持游戏的状态,使其与UI分离