简体   繁体   English

如何在 Java 中获取 JFormattedTextField 的长度?

[英]How to get length of a JFormattedTextField in Java?

I have a problem when I am trying to get the size of a JFormattedTextField.当我尝试获取 JFormattedTextField 的大小时遇到​​问题。 Actually I need the user to enter a simple pinCode, and then get the size of what he enters to loop on it right after it.实际上,我需要用户输入一个简单的 pinCode,然后获取他输入的内容的大小,以便在它之后立即循环。 If he entered 4 digits it's ok, or else he has to do it again.如果他输入了 4 位数字就可以了,否则他必须再次输入。 But when I run my project, I have an infinite loop with "Pin must be 4 digits"...但是当我运行我的项目时,我有一个无限循环,“Pin 必须是 4 位数字”......

I already found this link , but it did not fix my problem.我已经找到了这个链接,但它没有解决我的问题。

Here's my code :这是我的代码:

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 : bdd.txt :

1111
1234
2222
3333
4444
5555
6666
7777
8888
9999

How can I do that ?我怎样才能做到这一点 ? Any ideas ?有任何想法吗 ?

Thanks, Florent.谢谢,弗洛朗。

You seem to have misunderstood the concept of an actionListener: The Listener listens to your answer, and does nothing else.您似乎误解了 actionListener 的概念:Listener 会听取您的回答,而不会执行任何其他操作。 You have loops in the listener that wait for an correct amount of digits - thats wrong, you need to only handle one input in the listener (and after another click, the listener will be called again).您在侦听器中有循环等待正确数量的数字 - 这是错误的,您只需要处理侦听器中的一个输入(再次单击后,将再次调用侦听器)。 And so, for sure, because you got your loop with only one answer the user entered, you got a non-ending loop.因此,可以肯定的是,因为您的循环只包含用户输入的一个答案,所以您得到了一个永无止境的循环。 Just handle one input in the action listener, and you'll be fine.只需在动作侦听器中处理一个输入,就可以了。 Here is an description how to write it: http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html .以下是如何编写它的说明: http : //docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html

None of the answers actually work.没有一个答案实际上有效。 Short answer, you have to do the following check:简短的回答,您必须进行以下检查:

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

Explanation: the unicode character which is used in the NumberFormat is not a non-breaking space.说明: NumberFormat使用的 unicode 字符不是不间断空格。 After the \\u\u003c/code> there must be the hexadecimal representation of the character, that is .\\u\u003c/code>之后必须有字符的十六进制表示形式,即

Complete code:完整代码:

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();
            }
        });

    }
}

You can get the length of the text of a JFormattedTextField , say jtf here this way:你可以得到一个JFormattedTextField的文本长度,在这里说 jtf 这样:

jtf.getText().length(); 

Note : according to what you want use this :注意:根据您的需要使用此:

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

But the problem you've got is due to the way you've used the loops.但是您遇到的问题是由于您使用循环的方式。

I think you want to show a reaction when the user enters exactly for digits, and if so, you don't need a loop at all.我认为您想在用户完全输入数字时显示反应,如果是这样,您根本不需要循环。


According to the comments:根据评论:

  • Remove the loops (nTry < 3 ... )删除循环(nTry < 3 ...)
  • Define int nbTry = 0;定义int nbTry = 0; as a class member and keep track of it in your action listener.作为班级成员并在您的动作侦听器中跟踪它。
  • Inside the BoutonListener check if everything is right do whatever otherwise nTry++, and if nTry >=3 do whatever you want.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();
    }
}

You have an infinite loop in your code, so when the BoutonListener.actionPerformed is called for the first time it just spins there without exiting.您的代码中有一个无限循环,因此当第一次调用BoutonListener.actionPerformed时,它只是在那里旋转而不退出。

You will have to significantly modify your code.您将不得不显着修改您的代码。 Start with extracting the variables used in the do-while conditions into the fields, and update these fields each time the actionPerformed is called.首先将 do-while 条件中使用的变量提取到字段中,并在每次调用actionPerformed时更新这些字段。

You're running into an endless loop, because the user has no chance to reenter his PIN, if it doesn't match the length.您将陷入无限循环,因为如果 PIN 与长度不匹配,用户将没有机会重新输入他的 PIN。

Looping and Listeners don't work quite well in this way. Looping 和 Listeners 在这种情况下不能很好地工作。 Why don't you just keep the relevant variables (eg nbTry ) as members and perform your checks without looping?为什么不将相关变量(例如nbTry )保留为成员并执行检查而不循环?

Your mistake is in this if() condition :您的错误在于if()条件:

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

As the legnth of your pinCode is not equal to 4, you never validate the condition, and never break the do-while() loop.由于您的 pinCode 的长度不等于 4,因此您永远不会验证条件,也永远不会break do-while()循环。

By the way, using break is not a very good idea since you can always find a loop type or condition that allows you to avoid it !顺便说一句,使用break不是一个好主意,因为您总是可以找到允许您避免它的循环类型或条件!

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

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