簡體   English   中英

實現ActionListener的Java匿名類?

[英]Java anonymous class that implements ActionListener?

我最近做了一個編程任務,要求我們在代碼中實現一個由UML圖指定的程序。 有一次,該圖指定我必須創建一個顯示計數(從1開始)的匿名JButton,並在每次單擊時遞減。 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 () ,但還有另一種更優雅的方法來實現相同的結果嗎?

我通常會這樣:

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

AbstractAction實現了ActionListener,因此它應該滿足任務。

將這么多行代碼壓縮在一起可能是不好的做法,但如果你習慣於閱讀它,那么它可以非常優雅。

它非常難看,但您可以使用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的兩個位置訪問它。

實現多種類型通常是個壞主意。

雖然許多不好的軟件和教程都是這樣做的,但很少需要擴展JComponent類。 最近獲得支持的成語/ hack是Double Brace - 一個類只是子類,以便為它提供一個實例初始化器,其作用類似於來自其他語言的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上使用Swing組件。

在現實世界的計划中,我不會做那樣的事情,但考慮到你的任務要求,你幾乎無法做得更好。

那么有一種更優雅的方式來做到這一點。

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

您可以使用Groovy中的SwingBuilder來實現相同的結果,使用稍微簡潔的語法,例如偽代碼:

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

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

我不會在你的作業中使用這個,但是我看到學生們真的偏離了常規而得到了標記,但至少你可以把它作為進一步調查的可能途徑。

我覺得你現在擁有的東西絕對沒問題。

這是僅在家庭作業中被迫做的不良練習任務之一;-)壞事:

  • 使用ActionListener而不是Action本身就不好用
  • 結果,范圍界定問題起了泡沫
    • 反對范圍超出必要范圍
    • 需要訪問actionPerformed中的按鈕(通過類型轉換或訪問周圍對象的api)
  • 不可讀(又名:不可維護)的代碼

但是,那么..我們無法抗拒,我們可以;-)這是一個使用Action的版本,對於前兩個問題是干凈的(或者我認為),與其他所有例子一樣難以理解(當然我作弊:首先實施匿名類,然后讓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);
        }}
    );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM