当扩展类时出现错误

3
我对Java还不太熟悉,所以我不知道哪里出了问题。这里有一段代码,执行时应该会打开一个窗口,但每当我在ButtonHandler类中扩展ColoredWordsExperiment类时,窗口会无限快速地弹出,几乎每次都导致我的电脑崩溃。如果我省略扩展,则可以正常工作,但是我就不能在ButtonHandler类中使用ColoredWordsExperiment类的对象了...下面是代码(为了避免过长,我省略了一些不重要的东西)。
public class ColoredWordsExperiment {
    JFrame frame;
    ButtonHandler buttonHandler;

ColoredWordsExperiment(){
    frame = new JFrame("Colored Words Experiment");
    frame.setSize(1200, 150);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    button1 = new JButton("Matching");

    label1 = new JLabel("test");
    label1.setPreferredSize(new Dimension(90, 40));

    JPanel labelContainer = new JPanel();
    labelContainer.add(label1);

    JPanel buttonContainer = new JPanel();
    buttonContainer.add(button1);

    frame.add(buttonContainer, BorderLayout.SOUTH);
    frame.add(labelContainer, BorderLayout.NORTH);

    buttonHandler = new ButtonHandler();
    button1.addActionListener(buttonHandler);
}

public static void main(String[] arg) {
     new ColoredWordsExperiment();
}

}

-

public class ButtonHandler extends ColoredWordsExperiment implements ActionListener {
@Override
public void actionPerformed(ActionEvent e){
    if (e.getActionCommand().equals("Matching")) {
        System.out.println("Matching");
        label1.setText("Text changed");
    }
}
}
4个回答

2
在这种情况下,没有必要扩展ColoredWordsExperiment。你只需要实现ActionListener
你本质上是在自身内部初始化了另一个ColoredWordsExperiment实例,并添加了一个额外的方法。这将导致构造函数再次被调用,从而重新创建GUI窗口。 有关详细信息,请参见继承
如果你想从ActionListener实现中更改ColoredWordsExperiment中的字段,则需要在构造时传递引用。
public class ButtonHandler implements ActionListener {
    ColoredWordsExperiment coloredWords;
    public ButtonHandler(ColoredWordsExperiment coloredWords) {
        this.coloredWords = coloredWords;
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("Matching")) {
            System.out.println("Matching");
            coloredWords.label1.setText("Text changed");
        }
    }
}

在这种情况下,您还可以选择创建一个匿名内部类。使用这种技术,您可以完全摆脱ButtonHandler类。
ColoredWordsExperiment中,而不是

buttonHandler = new ButtonHandler();
button1.addActionListener(buttonHandler);

您可以使用

button1.addActionListener(new ActionListener() {
    if (e.getActionCommand().equals("Matching")) {
        System.out.println("Matching");
        label1.setText("Text changed");
    }
});

查看匿名类


1
你应该向他解释代码为什么会那样运作。 - Alvaro
好的,但是我想在单击“匹配”按钮时更改label1的文本,如果不在ButtonHandler中扩展ColoredWordsExperiment,我该如何做到这一点?因为如果我不扩展ColoredWordsExperiment,label1.setText(“文本已更改”)将无法工作。 - Ken
编辑以添加更多细节,以及匿名内部类的解释。这两种解决方案都应该考虑到这一点。 - Justin
谢谢!我正在使用第一种方法,因为我不理解第二种方法(看起来实际上更容易但是好吧)。不过我还有一个问题,如果我使用第一种方法,在ColoredWordsExperiment类中的“buttonHandler = new ButtonHandler(what to put here);”中应该传递什么参数? - Ken
你将会把 ColoredWordsExperiment 实例的引用传递给构造函数。因此使用buttonHandler = new ButtonHandler(this); - Justin

1
在父类的构造函数中,您正在创建其中一个ButtonHandlers,反过来,又再次运行构造函数代码。 您不应该在构造函数中实例化此类(或者如果您尝试使用相同名称的类,则应该使用不同的名称)。

0

好的,我可以看到你的问题是什么。现在我不知道为什么你想要扩展它,我只是试图回答你的问题(因为没有必要将动作监听器扩展到主类)。当你定义类方法时,你没有放置一个public,在主方法下运行时可能会混淆并制造无限框架。你应该改成这样:

public class ColoredWordsExperiment {
    JFrame frame;
    ButtonHandler buttonHandler;

   public ColoredWordsExperiment(){//add the public!
    frame = new JFrame("Colored Words Experiment");
    frame.setSize(1200, 150);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    button1 = new JButton("Matching");

    label1 = new JLabel("test");
    label1.setPreferredSize(new Dimension(90, 40));

    JPanel labelContainer = new JPanel();
    labelContainer.add(label1);

    JPanel buttonContainer = new JPanel();
    buttonContainer.add(button1);

    frame.add(buttonContainer, BorderLayout.SOUTH);
    frame.add(labelContainer, BorderLayout.NORTH);

    buttonHandler = new ButtonHandler();
    button1.addActionListener(buttonHandler);
   }

   public static void main(String[] arg) {
       new ColoredWordsExperiment();
    }

}

此外,在您的主类中将buttonHandler变量定义为ButtonHandler类,然后让ButtonHandler类扩展您的主类并不是一个好主意,因为这可能会导致循环。您应该要么不扩展第二个类,要么以不同的方式定义buttonHandler变量。

0
听起来你需要阅读并理解对象之间的区别。为了帮助你理解,我想用一个简化的例子来说明你最初对代码思考方式存在的问题:
class A {
    int x;
    B b = new B();
}

class B extends A {
}

class Main {
    public static void main(String args[]) {
        A a = new A();
        a.x = 42;
        a.b.x = 53;

        System.out.println(a.x);
        System.out.println(a.b.x);
    }
}

正如预期的那样,在`main()`函数中,对象`a`有一个名为`x`的字段,我们可以将其设置为42。然而,在`a`内部的对象`b`有一个与`a`对象内的`x`字段完全无关的名为`x`的自己的字段。
如果你能理解对象的概念,那么你将成为一名优秀的Java程序员。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接