我是 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
您提到您希望将消息文本放入 main 方法中,或者在 TestSwing 类以外的其他地方。一种方法是使用观察者设计模式,您允许其他类“观察”TestSwing 类——这是“可观察的”。有几种方法可以做到这一点,包括:
- 为 TestSwing 提供一个名为
addActionListener(ActionListener al)
的公共(public)无效方法,并在方法主体中添加传入提交按钮的监听器。这样,外部类就可以将 ActionListener 直接添加到该按钮并响应其事件。 - 为 TestSwing 提供一种方法来接受 ChangeListeners 并在其 ActionListener 中按下按钮时通知它们,或者
- 通过为 TestSwing 提供一个 PropertyChangeSupport 变量并公开添加和删除 PropertyChangeListener 方法,使它能够使用 PropertyChangeListeners。这类似于 ChangeListener 的想法,但由于 PCL 可以监听多个状态更改,因此它提供了更多的灵 active 和功能,这是我目前更喜欢的。例如:
最新版本的 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();
}
}
请阅读 Observer Design Pattern获取更多信息。
关于Swing GUI 不等待用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6935918/