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

查看:82
本文介绍了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类之外的其他地方。一种方法是使用Observer设计模式,允许其他类观察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提供一个名为的公共void方法addActionListener( ActionListener al),并在方法体中添加传入提交按钮的侦听器。这样,外部类可以直接向该按钮添加ActionListener并响应其事件。

  • 为TestSwing提供接受ChangeListeners的方法,并在ActionListener中按下按钮时通知它们,或者

  • 通过为其提供PropertyChangeSupport变量并公开添加和删除PropertyChangelistener方法,使TestSwing能够使用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();
   }

}

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

Please read up on the Observer Design Pattern for more information.

这篇关于Swing GUI不等待用户输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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