2014-01-07 74 views
0

這是我的代碼是什麼樣子的開頭:https://gist.github.com/anonymous/8270001
現在我去掉了ActionListener到一個單獨的類:https://gist.github.com/anonymous/8257038分開我的ActionListener從我的GUI類,不能正常工作

程序應該給我一個小UI,但它只是運行沒有任何UI彈出或錯誤。

有人告訴我:

在你的GUI類的構造函數,你正在創建一個新的nupuVajutus對象,但由於nupuVajutus擴展GUI類,當你創建一個nupuVajutus,你也是天生調用GUI類的構造函數默認,從而開創一個無限循環

如果這是真正的問題,那麼我不得不說,我並不好,並可以使用一些幫助獲得此程序分離的類工作。

+2

嘗試發佈[SSCCE](http://sscce.org)看起來這個問題很容易被複制到一個較小的示例程序中。 –

回答

2

你在做什麼擴展了GUI類。這無法加化妝,然後共享你在你的GUI類有一個字段field相同的字段

public class GUI { 
    String field = "Hello"; 
} 

僅僅因爲你的監聽器類extends GUI並不意味着他們將分享確切相同field對象。我認爲這就是你認爲是應該發生

public class Listener extends GUI implements ActionListener { 
    public void actionPerformed(ActionEvent e) { 
     field = "World"; 
    } 
} 

上面並沒有在GUIfield。如果您要這樣做,則需要以靜態方式訪問,如GUI.field = "World";。以上內容也是導致無限循環的原因,因爲您需要在GUI類中實例化Listener。這不是很好的練習或設計。

  • 一個選項會使用某種MVC模式。
  • 另一種選擇是將您需要的值傳遞給Listener類中的構造函數,並使用這些值在GUI類中實例化它。

運行這個例子,看看我說的。我有一個MyListener類,我傳遞一個Jlabel,同樣是JLabel在GUI類

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class FieldTest { 

    private JLabel label = new JLabel(" "); 
    private JButton button = new JButton("Set Text"); 

    public FieldTest() { 
     MyListener listener = new MyListener(label); 
     button.addActionListener(listener); 

     JFrame frame = new JFrame(); 
     frame.add(label, BorderLayout.CENTER); 
     frame.add(button, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new FieldTest(); 
      } 
     }); 
    } 
} 

class MyListener implements ActionListener { 
    JLabel label; 

    public MyListener(JLabel label) { 
     this.label = label; 
    } 

    @Override 
    public void actionPerformed(ActionEvent arg0) { 
     label.setText("Hello, FieldTest!"); 

    } 
} 
+0

也給你+1。與我的方法幾乎相同,但是它的範圍更窄(從設計角度來看,實際上可能更可取,因爲它明確指出ActionListener將控制哪些組件)。 – megaflop

3

你確實已經給出了答案,但你有什麼是不是一個無限循環,但無限遞歸,這最終會導致StackOverflowError。

這裏發生了什麼:

new GUI()調用new nupuVajutus()。這通過調用它的構造函數創建一個新的nupuVajutus對象。因爲nupuVajutus延伸了GUI,這意味着nupuVajutus對象是具有附加功能的GUI對象。因此,因爲它是一個GUI對象,所以需要調用一個GUI構造函數。 nupuVajutus構造函數沒有顯式調用super構造函數,所以它在執行之前隱式調用GUI()(無參數)構造函數。在這個新的調用GUI()構造,另一個new nupuVajutus()調用中遇到,等等,循環往復 ...

在我看來,你需要做的周圍面向對象編程的一些更多的研究,特別是主題子類,繼承,對象實例和封裝。有plenty of resources available to help you

在將ActionListener抽取到單獨的文件中後,您不應該將其更改爲擴展GUI。這擴展了(這就像一個藍圖),而不是實例(這就像使用藍圖構建的東西) - 記住:您可以創建一個類的多個實例。

此前,「nupuVajutus」ActionListener是一個內部類,所以它可以訪問所有封閉類的字段和方法。現在它不再是一個內部類,它需要傳遞一個對GUI實例的引用,以便它可以訪問它的方法。事情是這樣的:

public class NupuVajutus implements ActionListener { 
    private final GUI gui; 

    public NupuVajutus(GUI gui) { 
     this.gui = gui; 
    } 

    public void actionPerformed(ActionEvent e) { 
     // The GUI instance can now be accessed through the gui field, for example: 
     gui.something(); 
     // ... 
    } 
} 

而在GUI()構造:

NupuVajutus nV = new NupuVajutus(this); 

說實話,雖然,有什麼不對保持你的ActionListener作爲一個內部類。如果你永遠不會在GUI類之外使用這個類,那麼它可能更適合作爲內部類。

+0

+1這工作。也一樣:) –