2009-05-21 44 views
5

我最近在做一個編程任務,要求我們在代碼中實現一個由UML圖指定的程序。在某一點上,圖表指定我必須創建一個匿名JButton,它顯示一個計數(從一開始),並在每次點擊時遞減。 JButton和它的ActionListener都必須是匿名的。實現ActionListener的Java匿名類?

我想出了以下解決方案:

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(),但是有沒有另一種更優雅的方式來達到相同的結果?

+0

看一下你現在@Tim – Insane 2016-07-09 07:59:43

回答

11

我通常是這樣的:

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

AbstractAction實現的ActionListener所以這應該滿足的任務。

把這麼多行代碼擠在一起可能是不好的做法,但如果你習慣於閱讀它,那麼它可以很優雅。

+0

這實際上並沒有讓你更改動作偵聽器中的按鈕文本...這是一個相當尷尬的要求,我想不出一種方法來改善你的Alrea dy有。 – Cogsy 2009-05-21 04:43:37

+0

那麼匿名JButton中的計數器的公開聲明以及ActionListener中對它的非限定訪問是否可以? – Tim 2009-05-21 04:46:43

+0

是的,這是你能夠在這些領域獲得「處理」的唯一方法。請記住,內部類中的字段將隱藏在外部作用域中聲明的相同名稱的字段。希望你的編譯器/ IDE會明確地警告你。 – Cogsy 2009-05-21 04:58:08

1

我不會在現實世界的程序中這樣做,但考慮到您的任務中的要求,您幾乎可以做得更好。

1

那麼有一個更優雅的方式來做到這一點。

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

您可以在Groovy中使用SwingBuilder來獲得相同的結果,使用稍微簡潔的語法(例如,僞代碼:

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

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

我不會在你的作業,雖然利用這一點,我已經看到了學生真正從規範和偏離得到標記下來,但至少你可以將其作爲進一步調查的可能途徑。

我認爲你目前所擁有的絕對沒問題。

2

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

很少有必要擴展JComponent類,儘管很多不好的軟件和教程都這樣做。最近獲得成功的成語/攻擊是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樣板文件以確保Swing組件僅用於AWT EDT。

4

這是相當醜陋,但你可以做到以下幾點使用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的兩個地方訪問它。

0

這是被迫的功課只做;-)不好的事情不好的實踐任務之一:

  • ActionListener的,而不是行動的用法這是壞本身
  • 作爲結果,確定範圍的問題冒泡
    • 計數器的範圍比必需
    • 需要更寬的actionPerformed內部訪問按鈕(通過型鑄造或訪問周圍物體的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); 
     }} 
    );