【问题标题】:How do I get user input from a JTextField?如何从 JTextField 获取用户输入?
【发布时间】:2011-12-13 10:13:00
【问题描述】:

我正在尝试一个非常简单的表单,该表单旨在将用户输入带入 JTextField 并通过弹出对话框显示相同的输入。

我可以使用 setText() 对 JTextField 进行硬编码,使其具有预设编号。如果我这样做,我的程序将完美运行。

但是,当我将该字段留空并尝试 getText() 在弹出对话框中显示文本时,我要么得到一个空的弹出框,要么得到一个“空字符串”异常(我正在尝试解析字符串转双倍。)

package buttontest; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import javax.swing.*; import java.awt.event.ActionEvent; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; public class ButtonTest { public static void main(String[] args) { ButtonFrame frame = new ButtonFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } class ButtonFrame extends JFrame { @SuppressWarnings("LeakingThisInConstructor") public ButtonFrame() { setTitle("SunStream Loan Calculator v2.0"); setSize(900,900); ButtonPanel panel = new ButtonPanel(); panel.add(new JLabel("Enter your loan amount:")); loanAmt = new JTextField(40); panel.add(loanAmt); add(panel,BorderLayout.CENTER); } public JTextField loanAmt; class ButtonPanel extends JPanel implements ActionListener { private Component frame; public ButtonPanel() { final JButton b2 = new JButton("Calculate"); add(b2, BorderLayout.SOUTH); b2.setActionCommand("calculate"); b2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { ButtonFrame bf = new ButtonFrame(); if("calculate".equals(e.getActionCommand())) { JOptionPane.showMessageDialog(frame, bf.loanAmt.getText()); } } }); } @Override public void actionPerformed(ActionEvent ae) { throw new UnsupportedOperationException("Not supported yet."); } } }

任何帮助将不胜感激。我正在使用 KeyListener 或 KeyEvent 进行研究,但我不太了解它。

【问题讨论】:

    标签: java swing jtextfield


    【解决方案1】:

    您正在 b2 的 ActionListener 内创建一个“影子”ButtonFrame 变量。是的,bf 变量指的是与显示的 ButtonFrame 对象属于同一类的 ButtonFrame 对象,但它指的是完全不同且非可视化的对象。解决方案的关键是从实际显示的 ButtonFrame 对象中获取文本,这可以通过ButtonFrame.this 构造从内部类中获取:

         b2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               //!! ButtonFrame bf = new ButtonFrame();
               if ("calculate".equals(e.getActionCommand())) {
    
                  //!! note use of ButtonFrame.this:
                  JOptionPane.showMessageDialog(frame, ButtonFrame.this.loanAmt.getText());
               }
            }
    
         });
    

    接下来考虑使用公共 getter,而不是直接访问 JTextField 等字段。这减少了代码导致副作用的机会,例如无意中更改了 JTextField 对象的属性。

    例如(由 //!! 注释表示的更改):

    import java.awt.*;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    
    public class ButtonTest {
       public static void main(String[] args) {
          ButtonFrame frame = new ButtonFrame();
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setVisible(true);
       }
    }
    
    class ButtonFrame extends JFrame {
    
       private JTextField loanAmt; // !! Make field private
    
       @SuppressWarnings("LeakingThisInConstructor")
       public ButtonFrame() {
    
          setTitle("SunStream Loan Calculator v2.0");
          setSize(900, 900);
          ButtonPanel panel = new ButtonPanel();
          panel.add(new JLabel("Enter your loan amount:"));
          loanAmt = new JTextField(40);
          panel.add(loanAmt);
    
          add(panel, BorderLayout.CENTER);
       }
    
       // !! create a public method to get JTextField's text
       // !! without exposing the JTextField itself.
       public String getLoanAmtText() {
          return loanAmt.getText();
       }
    
       class ButtonPanel extends JPanel implements ActionListener {
          private Component frame;
    
          public ButtonPanel() {
    
             final JButton b2 = new JButton("Calculate");
             add(b2, BorderLayout.SOUTH);
             b2.setActionCommand("calculate");
             b2.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                   // !! ButtonFrame bf = new ButtonFrame();
                   if ("calculate".equals(e.getActionCommand())) {
    
                      //!! call public method on ButtonFrame object
                      JOptionPane.showMessageDialog(frame,
                            ButtonFrame.this.getLoanAmtText());
                   }
                }
    
             });
    
          }
    
          @Override
          public void actionPerformed(ActionEvent ae) {
             throw new UnsupportedOperationException("Not supported yet.");
          }
    
       }
    }
    

    【讨论】:

    • 这很有帮助!非常感谢您花时间看它!
    • 不客气!祝你在这个项目和你的 Java 学习上好运!
    • @Phoenix:这里的关键是所有关于引用。您需要引用实际显示的对象,而不是任何 ButtonFrame 对象。您对引用和引用变量了解得越多,您就越了解 Java 和 OOP。
    • 这很有意义。我正用头撞墙试图理解它。因此,在创建 3 个新文本字段时,我需要引用每个显示的对象 (ButtonFrame1.this -- ButtonFrame2.this -- ButtonFrame3.this) 以便对它们执行任何操作。我正在尝试制作一个简单的摊销计算器
    • @Phoenix:不,我猜不是。如果您有三个 JTextField 并且它们都保存在同一个类 ButtonFrame 中,那么您只需要一个 ButtonFrame 对象 ButtonFrame.this 的引用。然后,您将需要三个访问器方法来从三个 JTextField 中获取文本,或者需要一个访问器方法,该访问器方法接受一个参数,该参数以某种方式键入方法来确定要返回哪个 JTextField 的文本。
    【解决方案2】:

    您访问 loanAmt 的唯一方法是通过 ButtonPanel 本身。因为你在这个按钮上添加了 loanAmt 对吗?

    所以,如果您想访问 loanAmt。您必须在此按钮面板上获取所有组件。这是我的伪代码如何从 ButtonPanel 类访问您的 loanAmt

    b2.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            ButtonFrame bf = new ButtonFrame();
            if("calculate".equals(e.getActionCommand())) {
                // Get all component 
                java.awt.Component[] componentList = this.getComponents();
                JTextField txtField;
                String value;
                for (int i = 0; i < componentList.length; i++) {
                    if (componentList[i].getClass().getName().equals("javax.swing.JTextField")) {
                        txtField = (JTextField) componentList[i];
                        value = textField.getText();
                    }
                }
                if (value != null) JOptionPane.showMessageDialog(frame, value);
            }
        }
    });
    

    【讨论】:

    • 如果 JTextField 嵌套在 JPanel 中,而 JPanel 又嵌套在其他 JPanel 中怎么办?如果 GUI 的布局稍后发生变化怎么办?如果 GUI 有多个 JTextField 怎么办?不,这是一种非常脆弱的信息提取方式,很容易破坏并且不能很好地扩展。最好使用公共访问器方法。 herehere 描述了更好但更高级的方法。
    • @HovercraftFullOfEels 是的,如果 JTextField 位于嵌套面板内,那将是一场噩梦。我同意你的解决方案:)
    • 我编辑了你的帖子(添加了一个空格),所以我可以取消我的反对票。我建议您阅读我上面评论中的链接,因为它们简直太棒了,真的让我大开眼界。他们把我的建议放在我羞愧的回答中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 2020-02-11
    • 2020-02-17
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多