繁体   English   中英

Swing GUI不等待用户输入

[英]Swing GUI doesn't wait for user input

我是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可以监听多个状态变化,因此它提供了更大的灵活性和功能,这正是我所喜欢的。 例如:

最新版本的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 ...");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM