Как получить длину JFormattedTextField в Java?

У меня проблема, когда я пытаюсь получить размер JFormattedTextField. На самом деле мне нужно, чтобы пользователь ввел простой пин-код, а затем получил размер того, что он вводит, чтобы зациклить его сразу после него. Если он ввел 4 цифры, то все в порядке, или он должен сделать это снова. Но когда я запускаю свой проект, у меня есть бесконечный цикл с "Pin должен быть 4 цифры"...

Я уже нашел эту ссылку, но это не решило мою проблему.

Вот мой код:

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

Как я могу это сделать? Есть идеи?

Спасибо, Флоран.

6 ответов

Решение

Ни один из ответов на самом деле не работает. Короткий ответ, вы должны сделать следующую проверку:

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

Пояснение: символ Юникода \u0160 который используется в NumberFormat это не неразрывный пробел. После \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();
            }
        });

    }
}

Похоже, вы неправильно поняли концепцию actionListener: слушатель слушает ваш ответ и больше ничего не делает. У вас есть циклы в слушателе, которые ждут правильного количества цифр - это неправильно, вам нужно обрабатывать только один вход в слушателе (и после другого щелчка слушатель будет вызван снова). И так, конечно, потому что вы получили свой цикл только с одним ответом, введенным пользователем, вы получили бесконечный цикл. Просто обработайте один вход в слушателе действия, и все будет в порядке. Вот описание, как написать это: http://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html.

Вы можете получить длину текста JFormattedTextFieldскажи jtf вот так:

jtf.getText().length(); 

Примечание: в зависимости от того, что вы хотите использовать это:

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

Но проблема в том, что вы использовали петли.

Я думаю, что вы хотите показать реакцию, когда пользователь вводит именно цифры, и если это так, вам вообще не нужен цикл.


Согласно комментариям:

  • Удалить петли (nTry < 3 ...)
  • определять 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();
    }
}

У вас есть бесконечный цикл в вашем коде, поэтому, когда BoutonListener.actionPerformed вызывается впервые, он просто вращается там без выхода.

Вам придется значительно изменить свой код. Начните с извлечения переменных, используемых в условиях do-while, в поля и обновляйте эти поля каждый раз, когда actionPerformed называется.

Вы попадаете в бесконечный цикл, потому что у пользователя нет шансов повторно ввести свой PIN-код, если он не соответствует длине.

Циклы и Слушатели не очень хорошо работают таким образом. Почему бы вам просто не сохранить соответствующие переменные (например, nbTry) как члены и выполнять свои проверки без зацикливания?

Ваша ошибка в этом 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 это не очень хорошая идея, так как вы всегда можете найти тип или условие цикла, которые позволяют вам избежать этого!

Другие вопросы по тегам