Swing GUI 不等待用户输入 [英] Swing GUI doesn't wait for user input

查看:30
本文介绍了Swing GUI 不等待用户输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to Swing, and I have created a simple GUI class with a button and text field. There is a method in this class, String createAndShowUI(), and I want it to return the text of the text field. I have created another main class that calls this method and expects the text of text field to be returned. However my problem is that this method doesn't wait for the user to enter the text field and click on the button; it returns as soon as GUI is called. I want it to wait for the button click.

// 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 方法.例如(使用 //!! 注释突出显示的更改):

You're getting your msg String before the user has had a chance to change it, and the reason is that you're thinking in a procedural kind of way, and this won't work for Swing. In fact you've got to change your whole way of thinking in order to code event-driven programming like Swing. So msg isn't shown after a class is created but only after the user has initiated an event -- here the press of a button which prompts an ActionListener to call its actionPerformed method. For example (changes highlighted with the //!! comment):

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 类之外的其他地方.一种方法是使用观察者设计模式,允许其他类观察"TestSwing 类——这是可观察的".有几种方法可以做到这一点,包括:

Edit 2
You mentioned that you wanted to get the msg text into the main method, or somewhere else other than in the TestSwing class. One way is to use the Observer Design Pattern where you allow other classes to "observe" the TestSwing class -- which is the "observable". There are several ways this can be done, including:

  • 为TestSwing 提供一个名为addActionListener(ActionListener al) 之类的公共void 方法,并在方法主体中添加传递给提交按钮的侦听器.这样,外部类可以直接向该按钮添加 ActionListener 并响应其事件.
  • 为 TestSwing 提供一种方法来接受 ChangeListeners 并通知它们是否已在其 ActionListener 中按下按钮,或
  • 通过给 TestSwing 一个 PropertyChangeSupport 变量和公共添加和删除 PropertyChangelistener 方法,让它能够使用 PropertyChangeListeners.这就像 ChangeListener 的想法,但由于 PCL 可以侦听多个状态更改,因此它提供了更多的灵活性和功能,这是目前我更喜欢的.例如:
  • Giving TestSwing a public void method called something like addActionListener(ActionListener al), and in the method body add the listener passed in to the submit button. That way outside classes can add an ActionListener directly to that button and respond to its events.
  • Give TestSwing a way to accept ChangeListeners and notify them if the button has been pressed in its ActionListener, or
  • Give TestSwing the ability to use PropertyChangeListeners by giving it a PropertyChangeSupport variable and public add and remove PropertyChangelistener methods. This is like the ChangeListener idea but since a PCL can listen for multiple state changes, it gives more flexibility and power, and this is currently what I prefer. For example:

TestSwing 的最新版本:

Latest version of 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 GUI 不等待用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆