Swing GUI不等待用户输入

我是Swing的新手,我创建了一个带有按钮和文本字段的简单GUI类。 这个类中有一个方法, String createAndShowUI() ,我希望它返回文本字段的文本。 我创建了另一个调用此方法的主类,并期望返回文本字段的文本。 但是我的问题是这个方法不等待用户输入文本字段并单击按钮; 一旦调用GUI就会返回。 我希望它等待按钮点击。

 // TestSwing.java import javax.swing.*; import java.awt.*; import java.awt.event.*; public class TestSwing extends JPanel implements ActionListener { JButton submit; JTextField t1; String msg = "No Msg"; public TestSwing() { submit = new JButton("Submit"); t1 = new JTextField(10); submit.addActionListener(this); setLayout(new FlowLayout()); add(t1); add(submit); } public void actionPerformed(ActionEvent e) { if(e.getSource() == submit) { msg = t1.getText(); } } public String createAndShowUI() { JFrame f = new JFrame("Sample frame"); f.add(new TestSwing()); f.pack(); f.setVisible(true); return msg; } } //Main.java public class Main { public static void main(String[] arg) { System.out.println(new TestSwing().createAndShowUI()); } } 

在用户有机会改变它之前你得到你的msg字符串,原因是你正在以程序的方式思考,这对Swing不起作用。 事实上,你必须改变你的整个思维方式,以便编写像Swing这样的事件驱动编程。 因此,在创建一个类之后,msg不会显示,但只有在用户启动了一个事件之后才显示 – 这里按下一个按钮,提示ActionListener调用其actionPerformed方法。 例如(使用//!!注释突出显示的更改):

 import javax.swing.*; import java.awt.*; import java.awt.event.*; // Significant changes noted with the //!! comment public class TestSwing extends JPanel implements ActionListener { JButton submit; JTextField t1; String msg = "No Msg"; public TestSwing() { submit = new JButton("Submit"); t1 = new JTextField(10); submit.addActionListener(this); setLayout(new FlowLayout()); add(t1); add(submit); } public void actionPerformed(ActionEvent e) { if (e.getSource() == submit) { msg = t1.getText(); //!! Display msg only **after** the user has pressed enter. System.out.println(msg); } } public void createAndShowUI() { //!! Don't have method return anything JFrame f = new JFrame("Sample frame"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //!! close GUI f.add(new TestSwing()); f.pack(); f.setLocationRelativeTo(null); // center GUI f.setVisible(true); //!! return msg; // get rid of } public static void main(String[] arg) { new TestSwing().createAndShowUI(); } } 

编辑2
您提到要将msg文本放入main方法或TestSwing类以外的其他位置。 一种方法是使用Observer设计模式,允许其他类“观察”TestSwing类 – 这是“可观察的”。 有几种方法可以做到,包括:

  • 为TestSwing提供一个名为addActionListener(ActionListener al)的公共void方法,并在方法体中添加传入提交按钮的侦听器。 这样,外部类可以将ActionListener直接添加到该按钮并响应其事件。
  • 为TestSwing提供一种接受ChangeListeners的方法,并在ActionListener中按下按钮时通知它们,或者
  • 通过为其提供PropertyChangeSupport变量并公开添加和删除PropertyChangelistener方法,使TestSwing能够使用PropertyChangeListeners。 这就像ChangeListener的想法一样,但由于PCL可以监听多个状态变化,因此它提供了更大的灵活性和function,而这正是我所喜欢的。 例如:

最新版本的TestSwing:

 import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.*; @SuppressWarnings("serial") public class TestSwing extends JPanel { public static final String MESSAGE = "Message"; private JButton submit; private JTextField mainTextField; private String message = "No Msg"; private PropertyChangeSupport propSupport = new PropertyChangeSupport(this); public TestSwing() { submit = new JButton("Submit"); mainTextField = new JTextField(10); submit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { submitActionPerformed(e); } }); setLayout(new FlowLayout()); add(mainTextField); add(submit); } public void addPropertyChangeListener(PropertyChangeListener listener) { propSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propSupport.removePropertyChangeListener(listener); } public void setMessage(String newValue) { String oldValue = message; this.message = newValue; PropertyChangeEvent event = new PropertyChangeEvent(this, MESSAGE, oldValue, newValue); propSupport.firePropertyChange(event); } private void submitActionPerformed(ActionEvent e) { if (e.getSource() == submit) { setMessage(mainTextField.getText()); } } public static void createAndShowUI() { TestSwing testSwing = new TestSwing(); testSwing.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals(TestSwing.MESSAGE)) { System.out.println("message = " + evt.getNewValue()); } } }); JFrame f = new JFrame("Sample frame"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(testSwing); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] arg) { createAndShowUI(); } } 

请阅读观察器设计模式以获取更多信息。

Swing是事件驱动的。 无论你想在哪里使用,都应该调用msg作为动作监听器被调用的结果。

或者,您可以使用JOptionPane一个现成解决方案

 String userInput = JOptionPane.showInputDialog("Please enter ...");