代码之家  ›  专栏  ›  技术社区  ›  Tim

实现ActS听说音的Java匿名类?

  •  5
  • Tim  · 技术社区  · 17 年前

    我最近做了一个编程任务,要求我们在代码中实现由UML图指定的程序。在某一点上,图表指定我必须创建一个匿名jbutton,该jbutton显示一个计数(从1开始),并在每次单击时递减。jbutton和它的actionListener都必须是匿名的。

    我提出了以下解决方案:

    public static void main(String[] args) {
      JFrame f = new JFrame("frame");
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setSize(400, 400);
    
      f.getContentPane().add(new JButton() {
    
        public int counter;
    
        {
          this.counter = 1;
          this.setBackground(Color.ORANGE);
          this.setText(this.counter + "");
    
          this.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
              counter --;
              setText(counter + "");
            }
          });
    
        }
      });
    
      f.setVisible(true);
    
    }

    这将添加一个匿名jbutton,然后添加另一个(内部)匿名actionListener来处理事件,并根据需要更新按钮的文本。有更好的解决方案吗?我很确定我不能宣布匿名 JButton implements ActionListener () 但是有没有其他更优雅的方法来达到同样的结果呢?

    6 回复  |  直到 17 年前
        1
  •  12
  •   Cogsy    17 年前

    我通常这样做:

    JPanel panel = new JPanel();
    panel.add(new JButton(new AbstractAction("name of button") {
        public void actionPerformed(ActionEvent e) {
            //do stuff here
        }
    }));
    

    AbstractAction实现ActionListener,因此这应该满足任务的需要。

    把这么多行代码挤在一起可能是不好的做法,但是如果你习惯了阅读它,那么它可能非常优雅。

        2
  •  4
  •   Kothar    17 年前

    这很难看,但您可以使用ActionListener方法和匿名类执行以下操作:

      f.getContentPane().add(new JButton(new AbstractAction("name of button") {
          private int counter = 0;
    
          public void actionPerformed(ActionEvent e) {
              ((JButton) e.getSource()).setText(Integer.toString(counter--));
          }
      }) {
          {
              setText("1");
          }
      });
    

    为了更方便地访问计数器,您可以将其移动到类的顶级,并从调用settext的两个位置访问它。

        3
  •  2
  •   Tom Hawtin - tackline    17 年前

    实现多种类型通常是一个坏主意。

    很少有必要扩展 JComponent 课程,尽管有很多坏的软件和教程可以做到。最近流行的一个习惯用法是双括号-类只是子类,目的是给它一个实例初始化器,它的作用就像 with 其他语言的声明。

    在这种情况下,相关代码可以写为:

    JButton button = new JButton();
    button.addActionListener(new ActionListener() {
        int counter = 1;
        {
            updateText();
        }
        public void actionPerformed(ActionEvent arg0) {
            --counter;
            updateText();
        }
        private void updateText()
            setText(Integer.toString(counter));
        }
    });
    f.getContentPane(button);
    

    如果它变得更复杂,那么您可能需要创建一个外部类(它不实现 ActionListener 或延伸 JButton )处理数据。

    另外请注意,您应该使用 EventQueue.invokeLater 样板以确保回转组件仅用于AWT EDT。

        4
  •  1
  •   Erich Kitzmueller    17 年前

    我不会在现实生活中做这样的事情,但是考虑到你的任务要求,你几乎做不到更好。

        5
  •  1
  •   Jonathan Holloway    17 年前

    有一种更优雅的方式。

    不幸的是,它不是核心Java/Swing方法。

    您可以在groovy中使用swingbuilder来实现相同的结果,使用稍微更简洁的语法,例如psuedo代码:

    button(text: '' + counter,
             actionPerformed: {counter--; text = '' + counter + ''},
             constraints:BL.SOUTH)
    

    [ http://groovy.codehaus.org/Swing+Builder][1]

    不过,我在你的作业中不会用到这个,我见过学生 真的? 偏离标准并为之做标记,但至少你可以把它作为进一步调查的可能途径。

    不过,我认为你目前的状况绝对不错。

        6
  •  0
  •   kleopatra Aji kattacherry    15 年前

    这是一项只能在家庭作业中完成的不好的实践任务;-)不好的事情:

    • 使用actionListener而不是本身不好的action
    • 结果,范围界定问题冒出来了。
      • 计数器的范围比需要的范围宽
      • 需要访问已执行操作中的按钮(通过类型转换或访问周围对象的API)
    • 不可读代码

    但是,然后…我们不能抗拒,是吗;-)这里有一个版本使用的操作,对于前两个问题是干净的(或者我认为是干净的),和所有其他例子一样不可读的(当然,我作弊了:首先实现匿名类,然后让IDE进行内联

        f.add(new JButton(new AbstractAction() {
    
            int counter = 1;
            { // constructor block of action
                updateName();
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                counter--;
                updateName();
            }
    
            private void updateName() {
                putValue(Action.NAME, "" + counter);
            }
    
        })  { // subclass button 
              {  // constructor block button
                setBackground(Color.PINK);
            }}
        );