Dra*_*eel 1 java user-interface swing multithreading
我意识到你需要使用Event Dispatch Thread来避免冻结和死锁,但在这里,我遇到了冻结问题.由于封装的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();
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
这是扩展JFrame的第二个类.这是冻结的GUI.如果你看一下gameEngine()方法,你会注意到String input = keyboard.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");
}
}
Run Code Online (Sandbox Code Playgroud)
您的问题是扫描程序阻止了Swing事件线程,阻止您的GUI绘制和与用户交互.一个简单的解决方案是在后台线程中执行Scanner交互.更好的解决方案是完全摆脱Scanner(System.in)并通过GUI获得所有用户交互.控制台I/O和GUI I/O不应混用.
使用JTextField和布局管理器获取和响应输入的简单示例:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
@SuppressWarnings("serial")
public class Fu22GamePanel extends JPanel {
private static final int COLS = 50;
private static final int ROWS = 25;
private static final int GAP = 3;
private JTextField entryField = new JTextField(COLS);
private JTextArea textArea = new JTextArea(ROWS, COLS);
private String playerName;
public Fu22GamePanel(String name) {
this.playerName = name;
textArea.setFocusable(false);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
EntryAction entryAction = new EntryAction("Submit", KeyEvent.VK_S);
entryField.setAction(entryAction);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
bottomPanel.add(entryField);
bottomPanel.add(new JButton(entryAction));
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout(GAP, GAP));
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
private class EntryAction extends AbstractAction {
public EntryAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
String text = entryField.getText();
entryField.setText("");
textArea.append("> " + text + "\n");
entryField.requestFocusInWindow();
}
}
private static class WelcomePanel extends JPanel {
private JTextField playerNameField = new JTextField(10);
public WelcomePanel() {
int wpGap = 20;
setBorder(BorderFactory.createEmptyBorder(wpGap, wpGap, wpGap, wpGap));
add(new JLabel("Enter Player Name:"));
add(playerNameField);
}
public String getPlayerName() {
return playerNameField.getText();
}
}
private static void createAndShowGui() {
WelcomePanel welcomePanel = new WelcomePanel();
int response = JOptionPane.showConfirmDialog(null, welcomePanel, "Welcome to the Game", JOptionPane.OK_CANCEL_OPTION);
if (response != JOptionPane.OK_OPTION) {
return;
}
String name = welcomePanel.getPlayerName();
Fu22GamePanel mainPanel = new Fu22GamePanel(name);
JFrame frame = new JFrame("Game -- Player: " + name);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
498 次 |
| 最近记录: |