2016-11-22 166 views
-1

所以我開始玩Java中的javax.swing包類。我創建了一個按鈕,並希望爲其添加功能,所以我實現了ActionListener接口來收聽由我的按鈕創建的事件爲什麼在將對象作爲參數傳遞給類JButton的addActionListener()方法時使用this關鍵字?

以下是代碼塊。

public class SimpleGUI implements ActionListener {  
    JButton button; 

public void go() { 
    JFrame frame = new JFrame(); 
    button = new JButton("Click me"); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.getContentPane().add(button); 
    frame.setSize(300, 300); 
    frame.setVisible(true); 

    button.addActionListener(this); 
} 

@Override 
public void actionPerformed(ActionEvent event) { 
    button.setText("I've been clicked"); 
} 

當我對方法addActionListener方法,在API中擡起頭來,它指出,參數傳遞應該實現ActionListener接口,但是當我調整我的方法去()代碼的最後一行到

button.addActionListener(new SimpleGUI()); 

我相信這應該運行得很好,而且編譯器看起來很好,但是當我運行它時,畢竟我傳遞了實現ActionListener接口的對象,但是運行時錯誤太多。

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 
at simplegui.SimpleGUI.actionPerformed(SimpleGUI.java:29) 
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022) 
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348) 
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402) 
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252) 
at java.awt.Component.processMouseEvent(Component.java:6533) 
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324) 
at java.awt.Component.processEvent(Component.java:6298) 
at java.awt.Container.processEvent(Container.java:2236) 
at java.awt.Component.dispatchEventImpl(Component.java:4889) 
at java.awt.Container.dispatchEventImpl(Container.java:2294) 
at java.awt.Component.dispatchEvent(Component.java:4711) 
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888) 
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525) 
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466) 
at java.awt.Container.dispatchEventImpl(Container.java:2280) 
at java.awt.Window.dispatchEventImpl(Window.java:2746) 
at java.awt.Component.dispatchEvent(Component.java:4711) 
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758) 
at java.awt.EventQueue.access$500(EventQueue.java:97) 
at java.awt.EventQueue$3.run(EventQueue.java:709) 
at java.awt.EventQueue$3.run(EventQueue.java:703) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86) 
at java.awt.EventQueue$4.run(EventQueue.java:731) 
at java.awt.EventQueue$4.run(EventQueue.java:729) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76) 
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728) 
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201) 
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116) 
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101) 
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93) 
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

有人可以解釋背後的原因嗎?

+2

是的,它編譯 - 但我懷疑它做你想做的。由於您沒有顯示ActionListener實現代碼,因此很難確切知道會發生什麼,但基本上所有方法都將在SimpleGUI的* new *實例上調用,而不是'go()'的實例。被呼籲。我懷疑這就是你想要的。 –

+0

你需要發佈一個有效的[mcve]以及你的「過多的」錯誤來告訴你爲什麼會發生這種情況,但它可能與監聽器假設它與當前正在運行的GUI是同一個對象有很大關係。注意大部分更高級別的Swing編碼器都避免讓它們的視圖對象實現監聽器接口。 –

+0

我什麼都不做,只是打印一條消息,我已經編輯過,所以你可以看到。 –

回答

3

當您將this傳遞給.addActionListener()方法時,您將傳遞對當前類的實例的引用。當你通過new SimpleGUI()時,你傳入一個新創建的實例。新創建的實例未對您的button對象的實例進行評估,因此會在您嘗試設置其文本時生成錯誤。

另外,由於氣墊船Full Of Eels在評論中提及,所以在另一個類上實現ActionListener接口是更好的做法,然後將其傳遞到.addActionListener()

你也可以使用一個Anonymous Class,像這樣:

button.addActionListener(new ActionListener(){ 

     @Override 
     public void actionPerformed(ActionEvent e) { 

      button.setText("I've been clicked"); 
     } 
    }); 

這樣做可以定義你對你的ActionListener「當場」,並可以爲更清晰的代碼,一旦你開始進入更大的應用程序。

1

監聽器的按鈕變量爲null,因爲監聽器的SimpleGUI對象與顯示對象不同(正如我們前面提到的),所以從不調用監聽器對象的go()方法,所以按鈕永遠不會被分配有效的對象。

但是假設你擺脫了go()方法,並且在你的SimpleGUI構造函數中完成了所有的初始化,而你的代碼不會拋出NullPointerException,它將不會正確行爲,因爲你會改變顯示的文本更改偵聽器的SimpleGUI對象的狀態),而不是顯示的 SimpleGUI對象。

正如Gulllie指出的那樣,完全使用內部匿名類,私有內部類或單獨的偵聽器類。

相關問題