【问题标题】:How to get length of a JFormattedTextField in Java?如何在 Java 中获取 JFormattedTextField 的长度?
【发布时间】:2014-05-03 03:26:12
【问题描述】:

我在尝试获取 JFormattedTextField 的大小时遇到​​问题。实际上,我需要用户输入一个简单的 pinCode,然后获取他输入的内容的大小,以便在它之后立即循环。如果他输入了 4 位数字就可以了,否则他必须重新输入。但是当我运行我的项目时,我有一个“Pin must be 4 digits”的无限循环......

我已经找到了这个link,但它并没有解决我的问题。

这是我的代码:

package codePin;

import java.io.*;
import java.text.NumberFormat;
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Main extends JFrame {

    private static final long serialVersionUID = 1L;

    private JPanel container = new JPanel();
    private JFormattedTextField jtf = new JFormattedTextField(NumberFormat.getIntegerInstance());
    private JLabel label = new JLabel("Enter Pin: ");
    private JButton b = new JButton("OK");

    public Main() {
        this.setTitle("APP");
        this.setSize(300, 500);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);

        container.setBackground(Color.white);
        container.setLayout(new BorderLayout());
        JPanel top = new JPanel();
        Font police = new Font("Arial", Font.BOLD, 14);
        jtf.setFont(police);
        jtf.setPreferredSize(new Dimension(150, 30));
        jtf.setForeground(Color.BLUE);

        b.addActionListener(new BoutonListener());

        top.add(label);
        top.add(jtf);
        top.add(b); 

        this.setContentPane(top);
        this.setVisible(true);
    }

    class BoutonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            int nbTry = 0;
            boolean authenticated = false;

            do {
                do {

                    if (jtf.getText().length() != 4) { 
                        System.out.println("Pin must be 4 digits");
                    } else {
                        System.out.println("Checking...");
                    }

                    ArrayList<Integer> pins = new ArrayList<Integer>(); 
                    readPinsData(new File("bdd.txt"), pins);

                    String[] thePins = new String[pins.size()];
                    for (int i = 0; i < thePins.length; i++) {
                        thePins[i] = pins.get(i).toString();
                    }

                    String passEntered = String.valueOf(jtf);

                    for (int i = 0; i < thePins.length; i++) {
                        if (passEntered.equals(thePins[i]) && jtf.getText().length() == 4) {
                            System.out.println(":)");
                            authenticated = true;
                            break;
                        }
                    }
                } while (jtf.getText().length() != 4);
                if (!authenticated && jtf.getText().length() == 4) {
                    System.out.println(":(");
                    nbTry++;
                }
            } while (nbTry < 3 && !authenticated);
            //System.out.println("TEXT : jtf " + jtf.getText());

        }
    }

    // Function to read/access my pins database (file bdd.txt)
    static public boolean readPinsData(File dataFile, ArrayList<Integer> data) {
        boolean err = false;
        try {
            Scanner scanner = new Scanner(dataFile);
            String line;
            while (scanner.hasNext()) {
                line = scanner.nextLine();
                try {
                    data.add(Integer.parseInt(line));
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                    err = true;
                }
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            err = true;
        }

        return err;
    }

    public static void main(String[] args) {

        Main fen = new Main();
    }
}

bdd.txt:

1111
1234
2222
3333
4444
5555
6666
7777
8888
9999

我该怎么做?有什么想法吗?

谢谢,弗洛伦特。

【问题讨论】:

    标签: java eclipse swing jframe jformattedtextfield


    【解决方案1】:

    没有一个答案真正有效。简短的回答,您必须进行以下检查:

    if (jtf.getText().replaceAll("\u00A0","").length() != 4) {
        System.out.println("Pin must be 4 digits");
        JOptionPane.showMessageDialog(null,"Pin must be 4 digits");
        return;
    }
    

    说明:NumberFormat 中使用的 unicode 字符 \u0160 不是不间断空格。在\u之后必须有字符的十六进制表示,即\u00A0

    完整代码:

    package codePin;
    import java.io.*;
    import java.text.NumberFormat;
    import java.util.*;
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.concurrent.atomic.AtomicInteger;
    
    
    public class Main extends JFrame {
    
        private static final long serialVersionUID = 1L;
    
        private JPanel container = new JPanel();
        private JFormattedTextField jtf = new JFormattedTextField(NumberFormat.getIntegerInstance());
        private JLabel label = new JLabel("Enter Pin: ");
        private JButton b = new JButton("OK");
    
        public Main() {
            this.setTitle("APP");
            this.setSize(300, 500);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLocationRelativeTo(null);
    
            container.setBackground(Color.white);
            container.setLayout(new BorderLayout());
            JPanel top = new JPanel();
            Font police = new Font("Arial", Font.BOLD, 14);
            jtf.setFont(police);
            jtf.setPreferredSize(new Dimension(150, 30));
            jtf.setForeground(Color.BLUE);
    
            b.addActionListener(new BoutonListener());
    
            top.add(label);
            top.add(jtf);
            top.add(b);
    
            this.setContentPane(top);
            this.setVisible(true);
        }
    
        class BoutonListener implements ActionListener {
            private final AtomicInteger nbTry = new AtomicInteger(0);
            ArrayList<Integer> pins = readPinsData("bdd.txt");
            public void actionPerformed(ActionEvent e) {
                if (nbTry.get() > 2) {
                    JOptionPane.showMessageDialog(null, "Number of tries exceeded");
                    return;
                }
                final String passEntered=jtf.getText().replaceAll("\u00A0", "");
                if (passEntered.length() != 4) {
                    System.out.println("Pin must be 4 digits");
                    JOptionPane.showMessageDialog(null, "Ping must be 4 digits");
                    return;
                }
                System.out.println("Checking...");
                SwingWorker worker = new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        boolean authenticated = false;
                        if (pins.contains(Integer.parseInt(passEntered))) {
                            System.out.println(":)");
                            authenticated = true;
                        }
    
                        if (!authenticated) {
                            System.out.println(":(");
                            nbTry.incrementAndGet();
                        }
                        return null;
                    }
                };
                worker.execute();
            }
    
    
        }
    
        // Function to read/access my pins database (file bdd.txt)
        static public ArrayList<Integer> readPinsData(String dataFile) {
            final ArrayList<Integer> data=new ArrayList<Integer>();
            try {
                BufferedReader reader = new BufferedReader(new FileReader(new File(dataFile)));
                String line;
                try {
                    while ((line = reader.readLine()) != null) {
                        try {
                            data.add(Integer.parseInt(line));
                        } catch (NumberFormatException e) {
                            e.printStackTrace();
                            System.err.printf("error parsing line '%s'\n", line);
                        }
                    }
                } finally {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.err.println("error:"+e.getMessage());
            }
    
            return data;
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    Main fen = new Main();
                }
            });
    
        }
    }
    

    【讨论】:

    • 谢谢,它确实有效!这正是我一直在寻找的。我只有一个问题,如果我不使用 do wile loop anywhore,这怎么可能使用 nbTry 变量让用户尝试 3 次?
    • 顺便说一句,显然从未使用过 nbTry 的值.. 这很奇怪。
    • @FlorentP 我不知道您只给用户三次尝试。在那种情况下,你需要坚持nbTry,是的。
    • 等等是什么意思?
    • @FlorentP 更新了代码,它应该可以解决您的问题。问题是因为检查了jtf.getText().length()
    【解决方案2】:

    您似乎误解了 actionListener 的概念:Listener 会听取您的回答,而不会做任何其他事情。您在侦听器中有循环等待正确数量的数字 - 那是错误的,您只需要处理侦听器中的一个输入(再次单击后,将再次调用侦听器)。因此,可以肯定的是,因为你的循环只有一个用户输入的答案,所以你得到了一个无止境的循环。只需在动作侦听器中处理一个输入,就可以了。下面是如何写的说明:http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html.

    【讨论】:

      【解决方案3】:

      您的代码中有一个无限循环,因此当第一次调用BoutonListener.actionPerformed 时,它只是在那里旋转而不退出。

      您将不得不大幅修改您的代码。首先将 do-while 条件中使用的变量提取到字段中,并在每次调用 actionPerformed 时更新这些字段。

      【讨论】:

        【解决方案4】:

        您将陷入无限循环,因为如果长度不匹配,用户将无法重新输入其 PIN。

        循环和侦听器以这种方式不能很好地工作。为什么不将相关变量(例如nbTry)保留为成员并在不循环的情况下执行检查?

        【讨论】:

          【解决方案5】:

          您的错误在于if() 条件:

          for (int i = 0; i < thePins.length; i++) {
              if (passEntered.equals(thePins[i]) && jtf.getText().length() == 4) {
                  System.out.println(":)");
                  authenticated = true;
                  break;
              }
          }
          

          由于您的 pinCode 的长度不等于 4,因此您永远不会验证条件,也永远不会验证 break do-while() 循环。

          顺便说一句,使用break 不是一个好主意,因为您总能找到一种循环类型或条件来避免它!

          【讨论】:

          • 但是我尝试输入一个 4 位数的 pin,所以应该验证条件,因为 pinCode 的长度是 4 这种方式。没有?
          【解决方案6】:

          你可以得到一个JFormattedTextField的文本长度,这里说jtf这样:

          jtf.getText().length(); 
          

          注意:根据你的需要使用这个:

          String s = jtf.getText();
          s = s.replaceAll(",", "");
          if (s.length() != 4) 
          

          但是您遇到的问题是由于您使用循环的方式。

          我认为您希望在用户准确输入数字时显示反应,如果是这样,您根本不需要循环。


          根据cmets:

          • 删除循环 (nTry
          • int nbTry = 0; 定义为类成员并在您的动作监听器中跟踪它。
          • BoutonListener 中检查是否一切正常,否则请执行 nTry++,如果 nTry >=3 则执行您想要的任何操作。

          import java.io.*;
          import java.text.NumberFormat;
          import java.util.*;
          import javax.swing.*;
          import java.awt.*;
          import java.awt.event.*;
          
          public class Main extends JFrame {
              //-------------------------------here
              int nbTry = 0;
              //-------------------------------here
          
              private static final long serialVersionUID = 1L;
          
              private JPanel container = new JPanel();
              private JFormattedTextField jtf = new JFormattedTextField(NumberFormat.getIntegerInstance());
              private JLabel label = new JLabel("Enter Pin: ");
              private JButton b = new JButton("OK");
          
              public Main() {
          
          
                  jtf.getText().length();
                  this.setTitle("APP");
                  this.setSize(300, 500);
                  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  this.setLocationRelativeTo(null);
          
                  container.setBackground(Color.white);
                  container.setLayout(new BorderLayout());
                  JPanel top = new JPanel();
                  Font police = new Font("Arial", Font.BOLD, 14);
                  jtf.setFont(police);
                  jtf.setPreferredSize(new Dimension(150, 30));
                  jtf.setForeground(Color.BLUE);
          
                  b.addActionListener(new BoutonListener());
          
                  top.add(label);
                  top.add(jtf);
                  top.add(b); 
          
                  this.setContentPane(top);
                  this.setVisible(true);
              }
          
              class BoutonListener implements ActionListener {
                  public void actionPerformed(ActionEvent e) {
                      String s = jtf.getText();
                      s = s.replaceAll(",", "");
                      System.out.println(s);
                      System.out.println(s.length());
                      boolean authenticated = false;
                      if (nbTry > 3) {
                          //Oops, enough!
                      }
                      if (s.length() != 4) { 
                          System.out.println("Pin must be 4 digits");
                      } else {
                          System.out.println("Checking...");
                          //and check here!
                          ArrayList<Integer> pins = new ArrayList<Integer>(); 
                          readPinsData(new File("bdd.txt"), pins);
          
                          String[] thePins = new String[pins.size()];
                          for (int i = 0; i < thePins.length; i++) {
                              thePins[i] = pins.get(i).toString();
                          }
          
                          String passEntered = String.valueOf(jtf);
          
                          for (int i = 0; i < thePins.length; i++) {
                              if (passEntered.equals(thePins[i]) && jtf.getText().length() == 4) {
                                  System.out.println(":)");
                                  authenticated = true;
                                  break;
                              }
                          }
                          if (authenticated) {
                              //Congratulation! 
                          }
                          else {
                              nbTry++;
                          }
                      }
                  }
              }
          
              // Function to read/access my pins database (file bdd.txt)
              static public boolean readPinsData(File dataFile, ArrayList<Integer> data) {
                  boolean err = false;
                  try {
                      Scanner scanner = new Scanner(dataFile);
                      String line;
                      while (scanner.hasNext()) {
                          line = scanner.nextLine();
                          try {
                              data.add(Integer.parseInt(line));
                          } catch (NumberFormatException e) {
                              e.printStackTrace();
                              err = true;
                          }
                      }
                      scanner.close();
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                      err = true;
                  }
          
                  return err;
              }
          
              public static void main(String[] args) {
          
                  Main fen = new Main();
              }
          }
          

          【讨论】:

          • 是的,我就是这么做的。但是我不明白为什么在我运行项目时它不起作用。好像没有考虑长度。
          • 你使用循环不好。请告诉我你到底想做什么?
          • 我需要的是要求用户输入密码。如果他输入了 4 位数字,那么我们检查一个 .txt 文件,如果 pin 在那里(如果是 :),否则他还有 2 次尝试)。如果用户输入了错误大小的密码(即 1 位、2 位、3 位、5 位等),我们只是要求他再次输入一个简单的“密码必须为 4 位” ,但 nbTry 不会受到影响(我们可以将其同化为信用卡,虽然 PinEntered 不是 4 位数字,但我们仍然有 3 次尝试,因为根据定义, Pin 是 4 位数字)。
          • 我需要在类中的什么地方定义 nbTry ?
          • 我使用了 naimdjon 解决方案,因此我不再有这个无限循环问题。但是现在我希望在用户输入密码时为他提供 3 次机会。如果 pin 不在 bdd.txt 文件中,它会显示“:(”并且他还有 2 次尝试。但是如果我不再使用 do while 循环,我无法弄清楚。知道吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-05
          • 2013-11-18
          相关资源
          最近更新 更多