【问题标题】:action listener in another class - java另一个类中的动作监听器 - java
【发布时间】:2011-06-26 12:14:54
【问题描述】:

可能有两个类,并且在一个类中

arrayButtons[i][j].addActionListener(actionListner);

在另一个

ActionListener actionListner = new ActionListener() {
        public void actionPerformed(ActionEvent e) {

            for (int j = 0; j < arrayButtons.length; j++) {
                for (int i = 0; i < arrayButtons[j].length; i++) {
                    if (arrayButtons[j][i] == e.getSource()) {

                        if ((gameNumber == 2) && (playHand.getNumberOfCards() == 0)) {
                            if (player[j].getCard(i).getSuit() == Suit.HEARTS.toString() && player[j].hasSuitBesideHearts())
                                //second game
                                messageOnTable("xxx");

                            else{
                                arrayButtons[j][i].setVisible(false);
                                test[j].setIcon(player[j].getCard(i).getImage());
                                pnCardNumber[j].setText(Integer.toString(player[j].getCard(i).getNumber()));
                                pnCardName[j].setText(player[j].getCard(i).toString());
                                pnCardSuit[j].setText(player[j].getCard(i).getSuit());

                                playHand.addCard(player[j].getCard(i), j);

                                player[j].removeCard(i);

                            }

                        }

}

//还有更多 原因是我需要将按钮(swing)与动作监听器分开

我该怎么办?

谢谢

【问题讨论】:

  • 是的,您可以使用来自其他类的 ActionListener 或让一个单独的类实现 ActionListener 接口,但魔鬼在细节中。如果我们了解有关您的计划的更多详细信息,我们可以更轻松地为您提供建议。

标签: java swing listener


【解决方案1】:

不仅可以将这两者分开,还建议这样做(请参阅 MVC 模式 - 它主要是关于分离按钮等屏幕控件和程序的逻辑)

我想到的最简单的方法是编写一个实现ActionListener 接口的命名类,如下所示:

public class SomeActionListener implements ActionListener{

    private JTextField textField1;
    private JComboBox combo1;
    private JTextField textField2;
    //...

    public SomeActionListener(JTextField textField1, JComboBox combo1, 
                                          JTextField textField2){
        this.textField1=textField1;
        this.combo1=combo1;
        this.textField2=textField2;
        //...
    }

    public void actionPerformed(ActionEvent e) {
        //cmd
    }

}

然后将其添加到您的按钮中:

ActionListener actionListener = new SomeActionListener(textField1, combo1, textField2);
someButton.addActionListener(actionListener);

【讨论】:

  • 我的问题是动作监听器有很多像按钮一样摆动的变量,所以,当我换到另一个类时,我遇到了问题
  • @user:这很棘手。有关一种可能的解决方案,请参阅我的更新答案。您可以做的另一件事是为 JFrame 上的所有组件设置 getter 方法,然后仅将 jFrame 实例传递给侦听器。
  • @user:同样,您可以通过编辑上面的原始帖子提供的详细信息越多,我们可以提供的信息就越多。
  • 它要复杂得多,因为涉及许多按钮数组和循环(52-纸牌游戏)
  • @user:不是真的。只需传递整个数组并在侦听器中循环。一个数组可能有很多元素,但它仍然是一个引用。
【解决方案2】:

回答:“我的问题是动作监听器有很多像按钮一样摆动的变量,所以,当我切换到另一个类时,我遇到了问题”

您的动作侦听器类可以有一个构造函数,该构造函数接受视图类类型的参数:

public class Listener implements ActionListener {
  private final MyViewClass mView;
  public Listener(MyViewClass pView) {
    mView = pView;
  }

  public void actionPerformed(ActionEvent e) {
    // can use mView to get access to your components.
    mView.get...().doStuff...
  }
}

那么在你看来:

Listener l = new Listener(this);
button.addActionListener(l);

【讨论】:

    【解决方案3】:

    您可以通过使用嵌套类轻松做到这一点, 但我认为最好的方法是将父对象作为参数传递给对象的构造并将其用作动作处理程序;

    //**parent class - Calculator **//
    
    public class Calculator extends JFrame implements ActionListener{
    
        private DPanel dPanel;
        private JTextField resultText;
    
        public Calculator(){
            // set calc layout
            this.setLayout(new BorderLayout(1,1));
            dPanel = new DPanel(this); // here is the trick ;)
        }
        public void actionPerformed(ActionEvent e) {
            String command = e.getActionCommand();
            resultText.setText(command);
            // **** your code ****/
        }    
    }
    
    
    
    //**inner class - DPanel**//
    
    public class DPanel extends JPanel{
    
        private JButton digitsButton[];
        private JButton dotButton,eqButton;
    
        public DPanel(Calculator parent){
            //layout
            this.setLayout(new GridLayout(4,3,1,1));
    
            // digits buttons
            digitsButton = new JButton[10];
            for (int i=9;i>=0;i--){
                digitsButton[i] = new JButton(i+"");
                digitsButton[i].addActionListener(parent); // using parent as action handler ;)
                this.add(digitsButton[i]);
            }
         }
    }
    

    【讨论】:

    • 非常非常有用且简单明了,尤其是在花了很多时间试图理解 MVC 和 CardLayout 之后(不过,我仍然想学习这些东西)。
    • 它没有完全解耦,但它是一个解决方案!呸!
    • 这个解决方案在处理复杂的 GUI 和同样复杂的处理程序时会变得非常混乱。对于您提供的代码量来说工作正常,但当文件变大时,它肯定不是一个可维护的解决方案。 -1
    • @skubski 实际上从我长期使用 Java 的经验来看,像 java 这样的语言并不认可它对 UI 的效率:P,我认为这就是像“javascript”和“Actionscript”这样的脚本语言的原因用于 UI,无论如何使用清晰直接的解决方案总是赢得标准,请观看 Facebook 介绍“React 框架”时的视频,你会知道 MVC 对复杂的 UI 是多么糟糕,我相信你从来没有遇到过职业生涯
    【解决方案4】:

    这有点跑题了,但你绝对不应该使用== 运算符来比较Strings,就像你在这一行上所做的那样:

    if (player[j].getCard(i).getSuit() == Suit.HEARTS.toString()
    

    这是因为Strings 是指针,而不是实际值,使用== 运算符可能会出现意外行为。请改用someString.equals(otherString) 方法。还有

    "String to compare".equals(stringVariable)
    

    比其他方式好很多

    stringVariable.equals("String to compare to")
    

    因为在第一个示例中,如果 stringVariable 为 null,您将避免收到 NullPointerException。它只是返回 false。

    【讨论】:

      【解决方案5】:

      是的,可以做到。这很简单;在一个类中你有你的按钮,在另一个类中你只需要实现一个 ActionListener 并让你的 //cmd 分离该按钮的功能。为此,您需要使用 e.getActionCommand().equals(buttonActionCommand)。 示例代码:

      public class Click implements ActionListener{
      
          public Click(
           //input params if needed
           ){
      
          }
      
           public void actionPerformed(ActionEvent e) {
           if( e.getActionCommand().equals(buttonActionCommand){
           //cmd
           }
           } 
      
      }
      

      要在您的按钮上添加该侦听器,只需执行以下操作:

      buttonTest.addActionListener(new Click());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-10
        • 1970-01-01
        • 2011-08-30
        • 1970-01-01
        • 1970-01-01
        • 2021-03-13
        • 2021-07-02
        相关资源
        最近更新 更多