将我的ActionListener与GUI类分开,无法正常工作

时间:2014-01-07 11:45:18

标签: java class loops user-interface

这就是我的代码在开头的样子:https://gist.github.com/anonymous/8270001
现在,我将ActionListener删除为单独的类:https://gist.github.com/anonymous/8257038

该程序应该给我一个小UI,但它只是在没有任何UI弹出或错误的情况下继续运行。

有人告诉我这个:

  

在GUI类构造函数中,您正在创建一个新的nupuVajutus对象,但由于nupuVajutus扩展了GUI类,因此在创建nupuVajutus时,您本身也在调用GUI默认情况下类构造函数,从而创建一个无限循环

如果这确实是问题所在,那么我不得不说我不是那么好并且可以使用一些帮助让这个程序与分离的类一起工作。

2 个答案:

答案 0 :(得分:3)

你确实已经得到了答案,虽然你所拥有的不是无限循环,而是无限递归,最终会导致StackOverflowError。

以下是发生的事情:

new GUI()来电new nupuVajutus()。这通过调用其构造函数创建一个新的nupuVajutus对象。由于nupuVajutus扩展了GUI,这意味着nupuVajutus对象是具有附加功能的GUI对象。因此,因为它是GUI对象,所以需要调用GUI构造函数。 nupuVajutus构造函数没有显式调用super构造函数,因此它在执行之前隐式调用GUI()(无参数)构造函数。在对GUI()构造函数的新调用中,遇到了另一个new nupuVajutus()调用,依此类推, ad infinitum ...

在我看来,您需要围绕面向对象编程进行更多研究,特别是子类,继承,对象实例和封装等主题。有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类之外使用该类,那么最好将它保留为内部类。

答案 1 :(得分: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";
    }
}

上述内容与field中的GUI无关。如果您这样做,则需要以行GUI.field = "World";之类的静态方式访问。以上也是导致无限循环的原因,因为您需要在Listener类中实例化GUI。这不是一个很好的练习或设计。

  • 一种选择是使用某种MVC模式。
  • 另一种选择是将您需要的值传递给Listener类中的构造函数,并使用这些值在GUI类中实例化它。

运行此示例以查看我正在谈论的内容。我有一个MyListener类,我将Jlabel传递给GUI类中的JLabel

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!");

    }
}