2014-01-07 42 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这工作。也一样:) –