Как заставить JButtons печатать целые числа в JTextField с помощью прослушивателя действий и события действия?

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

public JButton jbtOne = new JButton(STANDARD_BTN_TEXTS[0][0]);

Итак, если пользователь нажимает «jbtOne», скажем, 4 раза. JTextField должен отображать 1111. Моя проблема в том, что кнопка не отвечает на строку кода:

addActionListener(listener)

Как заставить JButtons печатать целые числа в JTextField? Я заставил это работать раньше, но с тех пор не смог заставить его снова работать после добавления более удобного для пользователя вида с помощью этой строки кода:

 private static final String[][] STANDARD_BTN_TEXTS = 
{
    {"1", "2", "3"},
    {"4", "5", "6"},
    {"7", "8", "9"},
    { "0" }

Может ли кто-нибудь указать мне в правильном направлении? Любая помощь приветствуется!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.JFrame;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractButton;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JPasswordField;

public class TerminalATM extends JFrame
{
private JPanel panel;
public final JPasswordField passwordField = new JPasswordField(2);
private static final String[][] STANDARD_BTN_TEXTS = 
{
    {"1", "2", "3"},
    {"4", "5", "6"},
    {"7", "8", "9"},
    { "0" }
};
private static final int GAP = 5;
private static final Font BTN_FONT = new Font(Font.DIALOG, Font.BOLD, 20);
public JButton jbtOne = new JButton(STANDARD_BTN_TEXTS[0][0]);
 private JTextField jtfNumber1 = new JTextField(8);//Define Number Field

public TerminalATM()
{       
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null); 

    JPanel standardPanel = createBtnPanel(STANDARD_BTN_TEXTS, "KeyPad");
    JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new GridLayout(0, 1));
    buttonPanel.add(jtfNumber1, BorderLayout.NORTH);
    buttonPanel.add(standardPanel, BorderLayout.SOUTH);



    BtnListener listener = new BtnListener();
    jbtOne.addActionListener(listener);

    TextFieldHandler handler = new TextFieldHandler();
    passwordField.addActionListener(handler);

    add(buttonPanel, BorderLayout.LINE_START);
    setSize(450, 500);
    setVisible(true);
}

//Create Unique Rows of Buttons
private JPanel createBtnPanel(String[][] texts, String title) {
    JPanel btnPanel = new JPanel();
    int rows = texts.length;
    int cols = texts[0].length;
    btnPanel.setLayout(new GridLayout(rows, cols, GAP, GAP));
    for (int row = 0; row < texts.length; row++) {
        for (int col = 0; col < texts[row].length; col++) {
            JButton btn = new JButton(texts[row][col]);
            btn.setFont(BTN_FONT);
            btnPanel.add(btn);
        }
    }
    btnPanel.setBorder(BorderFactory.createTitledBorder(title));
    return btnPanel;
  }


  private class TextFieldHandler implements ActionListener
 {

  @Override
  public void actionPerformed(ActionEvent event)
  {
  String string = "";

 if(event.getSource()==passwordField)
 string = String.format("textField1: %s", event.getActionCommand());
 }
 } 

/**** Create Button Listener and Action Listener ****/
 class BtnListener implements ActionListener 
{
    @Override
 public void actionPerformed(ActionEvent e)
{
      /* This is where we would set each button to the action event */
      /* Only Button one for brevity */
   int int1=0;
 if(e.getSource().equals(jbtOne))
{
     int1 = 1;
  passwordField.setText(String.valueOf(int1));

  }
 }
 }


public static void main(String[] args)
{
    SwingUtilities.invokeLater(new Runnable()
    {
    public void run()
    {
    new TerminalATM();
    }
    });
   }
 }//EndTerminalATM

person Raoul Duke    schedule 15.07.2015    source источник


Ответы (3)


В следующем коде я заставил прослушиватель кнопок отвечать и выводить текст нажатой кнопки для отображения в текстовом поле. Все изменения задокументированы, начиная с /****, чтобы объяснить, что я сделал.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logging;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TerminalATM extends JFrame
{
    private JPanel panel;
    public final JPasswordField passwordField = new JPasswordField(2);
    private static final String[][] STANDARD_BTN_TEXTS =
        {
        {"1", "2", "3"},
        {"4", "5", "6"},
        {"7", "8", "9"},
        { "0" }
        };
    private static final int GAP = 5;
    private static final Font BTN_FONT = new Font(Font.DIALOG, Font.BOLD, 20);
    /**** what is the purpose of this JButton ? */
    public JButton jbtOne = new JButton(STANDARD_BTN_TEXTS[0][0]);
    private JTextField jtfNumber1 = new JTextField(8);//Define Number Field

    public TerminalATM()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        JPanel standardPanel = createBtnPanel(STANDARD_BTN_TEXTS, "KeyPad");
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(0, 1));
        buttonPanel.add(jtfNumber1, BorderLayout.NORTH);
        buttonPanel.add(standardPanel, BorderLayout.SOUTH);

        /**** The action listener should go on the button which is pressed
         see createBtnPanel  */
//      BtnListener listener = new BtnListener();
//      jbtOne.addActionListener(listener);

        /**** what is the purpose of this JPasswordField ?
         it is not being added to any JPanel */
        TextFieldHandler handler = new TextFieldHandler();
        passwordField.addActionListener(handler);

        add(buttonPanel, BorderLayout.LINE_START);
        setSize(450, 500);
        setVisible(true);
    }

    //Create Unique Rows of Buttons
    private JPanel createBtnPanel(String[][] texts, String title) {
        JPanel btnPanel = new JPanel();
        int rows = texts.length;
        int cols = texts[0].length;
        btnPanel.setLayout(new GridLayout(rows, cols, GAP, GAP));

        /**** create the listener */
        BtnListener listener = new BtnListener();
        for (String[] text : texts) {
            for (String element : text) {
                JButton btn = new JButton(element);
                btn.setFont(BTN_FONT);

                /**** add the listener to each button*/
                btn.addActionListener(listener);
                btnPanel.add(btn);
            }
        }
        btnPanel.setBorder(BorderFactory.createTitledBorder(title));
        return btnPanel;
    }


    private class TextFieldHandler implements ActionListener
    {

        @Override
        public void actionPerformed(ActionEvent event)
        {
            String string = "";

            if(event.getSource()==passwordField) {
                string = String.format("textField1: %s", event.getActionCommand());
            }
        }
    }

    /**** Create Button Listener and Action Listener ****/
    class BtnListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {

            /* This is where we would set each button to the action event */
            /* Only Button one for brevity */

            /**** what is the purpose of it ?   int int1=0; */

            /****  the event is generated by the button created in
             createBtnPanel so e.getSource()  can not be equal to
             jbtOne. It should be an instance of JButton  */

            if(e.getSource() instanceof JButton)
            {
                /**** get the JButton clicked */
                JButton button = (JButton) e.getSource() ;
                /**** display its text on the text field */
                jtfNumber1.setText(button.getText());
            }
        }
    }


    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                /**** new MultiplePanels(); is un defined */
                new TerminalATM();
            }
        });
    }

}//EndTerminalATM

Мне нужно лучше понять, какой функциональности вы хотите достичь с помощью поля пароля и прослушивателя действий, поэтому я могу попытаться помочь вам в дальнейшем, если это необходимо. (0:

person c0der    schedule 15.07.2015

Мне кажется, что вы не добавляете jbtOne на видимую панель. Ваш метод createBtnPanel создает свои собственные кнопки и добавляет их на панель без прослушивания действий.

Попробуйте изменить следующие строки внутреннего цикла createBtnPanel:

for (int row = 0; row < texts.length; row++) {
    for (int col = 0; col < texts[row].length; col++) {
        final String text = texts[row][col];
        final JButton btn = new JButton(text);
        btn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ev) {
                passwordField.setText(text);
            }
        });
        btn.setFont(BTN_FONT);
        btnPanel.add(btn);
    }
}

Дайте мне знать, если вы не понимаете, что это делает, или у вас есть какие-либо проблемы с этим.

Этот код также можно значительно упростить, если вы используете Java 8, но я предполагаю, что вы не хотите, чтобы мой ответ был простым.

person sprinter    schedule 15.07.2015
comment
Спасибо за помощь Спринтеру! Да, у меня проблемы с пониманием цели, и когда я реализую, я получаю сообщение об ошибке: доступ к локальным текстам переменных осуществляется из внутреннего класса; необходимо объявить окончательным. Что я и сделал, и пока не имеет никакого эффекта. Можете ли вы уточнить/объяснить свое предложение? (используя dr.java с компилятором: JDK 7.0) - person Raoul Duke; 15.07.2015
comment
Самый простой способ — скопировать текст в локальную конечную переменную. Я обновил ответ, чтобы отразить это. - person sprinter; 15.07.2015

Ваши слушатели используют passwordField, однако кажется, что вы добавили текстовое поле на свою панель, либо используйте passwordField, либо jtfNumber1.

person Ash    schedule 15.07.2015