简体   繁体   English

用Java实现多个ActionListener

[英]Implementing Multiple ActionListeners in Java

I am having trouble implementing multiple action listeners in my Java program. 我在Java程序中实现多个动作侦听器时遇到麻烦。 The program is a calculator that does basic functions with a basic GUI. 该程序是一个具有基本GUI功能的计算器。 From my research I have noticed that action listeners should go into different classes. 从我的研究中,我注意到动作侦听器应该分为不同的类别。 I have comprised my program of four action listeners but I keep getting a terrible amount of errors every time I run my program along with warnings for each action listener saying "The serializable class ClearListener does not declare a static final serialVersionUID field of type long" Any help with this would be greatly appreciated. 我的程序包含四个动作侦听器,但是每次运行程序时都会收到很多错误,并且每个动作侦听器都显示警告:“可序列化的类ClearListener不会声明类型为long的静态最终serialVersionUID字段”任何帮助将不胜感激。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
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.JTextField;


public class GUICalc extends JPanel {

    private static final long serialVersionUID = 1L;

    JButton[] numberButtons;
    JButton[] upButtons;

    JTextField field;
    double num1;

    double num2;

    double ans; 
    int op;

    DigitalListener listener1 = new DigitalListener();
    OperatorListener listener2 = new OperatorListener();
    ClearListener listerner3 = new ClearListener();
    EqualsListener listerner4 = new EqualsListener();

    // 0 = gridx 1 gridy 2 gridwidth 3 gridheight
    private int[][] numConstraints = new int[][] {
            {0, 4, 1, 1},
            {0, 1, 1, 1},
            {1, 1, 1, 1},
            {2, 1, 1, 1},
            {0, 2, 1, 1},
            {1, 2, 1, 1},
            {2, 2, 1, 1},
            {0, 3, 1, 1},
            {1, 3, 1, 1},
            {2, 3, 1, 1},
    };

    private int[][] upConstraints = new int[][] {
            {1, 4, 1, 1},
            {3, 4, 1, 1},
            {3, 3, 1, 1},
            {3, 2, 1, 1},
            {3, 1, 1, 1},
            {0, 5, 4, 1},
            {2, 4, 1, 1},
    };

    public GUICalc() {
        setPreferredSize(new Dimension(666, 666)); //width & heigth

        GridBagLayout layout; // used to be private
        GridBagConstraints gbc; // used to be private

        layout = new GridBagLayout();
        layout.columnWidths = new int[] {60, 60, 60, 60};
        layout.rowHeights = new int[] {60, 60, 60, 60, 60, 60};
        setLayout(layout);

        gbc = new GridBagConstraints();

            numberButtons = new JButton[10];

            numberButtons[0] = new JButton("0");
            numberButtons[1] = new JButton("1");
            numberButtons[2] = new JButton("2");
            numberButtons[3] = new JButton("3");
            numberButtons[4] = new JButton("4");
            numberButtons[5] = new JButton("5");
            numberButtons[6] = new JButton("6");
            numberButtons[7] = new JButton("7");
            numberButtons[8] = new JButton("8");
            numberButtons[9] = new JButton("9");

            for(int i = 0; i < numberButtons.length; i++){
                gbc.gridx = numConstraints[i][0];
                gbc.gridy = numConstraints[i][1];
                gbc.gridwidth = numConstraints[i][2];
                gbc.gridheight = numConstraints[1][3];
                gbc.fill = GridBagConstraints.BOTH;
                gbc.insets = new Insets(2, 2, 2, 2); 
                numberButtons[i].addActionListener(listener1);
                add(numberButtons[i], gbc);
                }

        upButtons = new JButton[7];

        upButtons[0] = new JButton(".");
        upButtons[1] = new JButton("/");
        upButtons[2] = new JButton("*");
        upButtons[3] = new JButton("-");
        upButtons[4] = new JButton("+");
        upButtons[5] = new JButton("=");
        upButtons[6] = new JButton("C");

            gbc.gridx = upConstraints[0][0];
            gbc.gridy = upConstraints[0][1];
            gbc.gridwidth = upConstraints[0][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[0].addActionListener(listener2);
            add(upButtons[0], gbc); 

            gbc.gridx = upConstraints[1][0];
            gbc.gridy = upConstraints[1][1];
            gbc.gridwidth = upConstraints[1][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[1].addActionListener(listener2);
            add(upButtons[1], gbc); 

            gbc.gridx = upConstraints[2][0];
            gbc.gridy = upConstraints[2][1];
            gbc.gridwidth = upConstraints[2][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[2].addActionListener(listener2);
            add(upButtons[2], gbc); 

            gbc.gridx = upConstraints[3][0];
            gbc.gridy = upConstraints[3][1];
            gbc.gridwidth = upConstraints[3][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[3].addActionListener(listener2);
            add(upButtons[3], gbc); 

            gbc.gridx = upConstraints[4][0];
            gbc.gridy = upConstraints[4][1];
            gbc.gridwidth = upConstraints[4][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[4].addActionListener(listener2);
            add(upButtons[4], gbc); 

            gbc.gridx = upConstraints[5][0];
            gbc.gridy = upConstraints[5][1];
            gbc.gridwidth = upConstraints[5][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[5].addActionListener(listerner4);
            add(upButtons[5], gbc); 

            gbc.gridx = upConstraints[6][0];
            gbc.gridy = upConstraints[6][1];
            gbc.gridwidth = upConstraints[6][2];
            gbc.gridheight = upConstraints[1][3];
            gbc.insets = new Insets(2, 2, 2, 2);
            upButtons[6].addActionListener(listerner3);
            add(upButtons[6], gbc);

        field = new JTextField();
        field.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        field.setEditable(false);
        field.setFont(new Font("Arial",Font.PLAIN, 24));
        field.setText(null);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 4;
        gbc.gridheight = 1;

        add(field, gbc);

    }


    public static void main(String [] args){
        JFrame frame = new JFrame("Calculator");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setLayout(new BorderLayout());
        frame.add(new GUICalc(), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);     

    }

}

class DigitalListener extends GUICalc implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == numberButtons[0]){
            field.setText(field.getText() + 0);
            }
            if(e.getSource() == numberButtons[1]){
            field.setText(field.getText() + 1);
            }
            if(e.getSource() == numberButtons[2]){
            field.setText(field.getText() + 2);
            }
            if(e.getSource() == numberButtons[3]){
            field.setText(field.getText() + 3);
            }
            if(e.getSource() == numberButtons[4]){
            field.setText(field.getText() + 4);
            }
            if(e.getSource() == numberButtons[5]){
            field.setText(field.getText() + 5);
            }
            if(e.getSource() == numberButtons[6]){
            field.setText(field.getText() + 6);
            }
            if(e.getSource() == numberButtons[7]){
            field.setText(field.getText() + 7);
            }
            if(e.getSource() == numberButtons[8]){
            field.setText(field.getText() + 8);
            }
            if(e.getSource() == numberButtons[9]){
            field.setText(field.getText() + 9);
            }
            if(e.getSource() == upButtons[0] && !field.getText().contains(".")) {
                field.setText(field.getText() + ".");
            }
    }
}

class OperatorListener extends GUICalc implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e){
        if(e.getSource() == upButtons[1]) {
            num1 = Integer.parseInt(field.getText());
            op = 4;
            field.setText("");
        }

        if(e.getSource() == upButtons[2]) {
            num1 = Integer.parseInt(field.getText());
            op = 3;
            field.setText("");
        }
        if(e.getSource() == upButtons[3]) {
            num1 = Integer.parseInt(field.getText());
            op = 2;
            field.setText("");
        }
        if(e.getSource() == upButtons[4]) {
            num1 = Integer.parseInt(field.getText());
            op = 1;
            field.setText("");
        }
    }
}

class ClearListener extends GUICalc implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == upButtons[6]) {
            field.setText("0.0");
        }
    }
}

class EqualsListener extends GUICalc implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == upButtons[5]) {
            num2 = Integer.parseInt(field.getText());

            if(op == 1){
                ans = num1 + num2;
            } else if(op == 2){
                ans = num1 - num2;

            } else if(op == 3){
                ans = num1 * num2;
            } else if(op == 4){
                ans = num1 / num2;
            } 

            op = 0;
            field.setText("" + ans);
        }
    }
}

Most probably you are getting Exception in thread "main" java.lang.StackOverflowError 您很可能Exception in thread "main" java.lang.StackOverflowError中遇到Exception in thread "main" java.lang.StackOverflowError

Do in this way: 这样做:

class OperatorListener implements ActionListener {

   private GUICalc guiCalc;
   public OperatorListener(GUICalc guiCalc){
       this.guiCalc=guiCalc;
   }
   // use guiCalc to refer the values
   ...
 }

and in GUICalc.java 并在GUICalc.java

OperatorListener listener2 = new OperatorListener(this);

Do same thing for all type of your custom listener. 对所有类型的自定义侦听器执行相同的操作。


You have created a cyclic dependencies between objects. 您已在对象之间创建了循环依赖关系。

GUICalc contains OperatorListener GUICalc包含OperatorListener

public class GUICalc extends JPanel {
   ...

   OperatorListener listener2 = new OperatorListener();
   ...

} }

OperatorListener is extending GUICalc class OperatorListener正在扩展GUICalc

class OperatorListener extends GUICalc implements ActionListener {...}

Now whenever GUICalc super class object is going to construct it tries to create the dependencies sub-class objects such as OperatorListener but now sub-class object can't be constructed until and unless super-class object is created. 现在,每当要构造GUICalc超类对象时,它都会尝试创建依赖项子类对象(例如OperatorListener但是直到并且除非创建了超类对象,才能构造子类对象。

Although the first answer was already accepted, some hints: 尽管第一个答案已经被接受,但有些提示:

The recommendation that "action listeners should be in different classes" is correct. “动作侦听器应位于不同的类中”的建议是正确的。 However, this does not mean that you should arbitrarily combine several ActionListeners into one class. 但是,这并不意味着您应该将多个ActionListener任意组合到一个类中。 While this is possible and may be feasible in some cases, there are solutions that are more appropriate for use-cases like yours. 尽管这是可行的,并且在某些情况下可能是可行的,但有些解决方案更适合像您这样的用例。

This could help you to simplify your code a little. 这可以帮助您稍微简化代码。 (If I had to clean it up, I'd start with the GridBagLayout and these numConstraints arrays - I think these are horrible - but this is a different story...). (如果必须清理它,我将从GridBagLayout和这些numConstraints数组开始-我认为它们很可怕-但这是另一numConstraints了。)。 Particularly, you could create a method that creates an anonymous ActionListener like this: 特别是,您可以创建一个创建匿名ActionListener的方法,如下所示:

private ActionListener createActionListener(final String string)
{
    return new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            field.setText(field.getText() + string);
        }
    };
}

Then you could create instances of these listeners and add them to the buttons: 然后,您可以创建这些侦听器的实例并将其添加到按钮中:

for(int i = 0; i < numberButtons.length; i++)
{ 
    ...
    numberButtons[i].addActionListener(
        createActionListener(String.valueOf(i)));
}

(Note that then you might not even have to store the numberButtons array as an instance variable in the best case...) (请注意,在最佳情况下,您甚至不必将numberButtons数组存储为实例变量...)

A similar concept could be applied to the operation-buttons. 类似的概念可以应用于操作按钮。 In general, I consider it as a good practice to use anonymous listeners to just "connect" a particular method call to one button, roughly like this: 通常,我认为使用匿名侦听器将特定方法调用“连接”到一个按钮是一个好习惯,大致如下:

someButton.addActionListener(new ActionListener()
{
    @Override
    public void actionPerformed(ActionEvent e)
    {
        doSomething();
    }
});

For many cases, it is even more beneficial to use Action s (see http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html ), but this is at least conceptually similar, in contrast to having an ActionListener that examines the event source or the action command. 在许多情况下,使用Action会更加有益(请参阅http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html ),但这至少在概念上是相似的,与具有一个ActionListener ,它检查事件源或action命令。

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

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