2

为什么以下代码不起作用?基本上,这是一个更难的程序的简化版本,在该程序中,我试图制作一个可运行的初始屏幕,其中包含一些选项,然后将按钮链接到不同的可运行文件,但这并没有按我预期的那样运行。

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

public class Runnables {
    static Runnable runone;
    static Runnable runtwo;
    static JFrame frame = new JFrame();
    static JButton button1 = new JButton("Initial screen");
    static JButton button2 = new JButton("After button click screen");

    public static void main(String[] args) {
        runone = new Runnable() {
            @Override
            public void run() {
                frame.removeAll();
                frame.revalidate();
                frame.repaint();
                frame.add(button2);
            }

        };
        runtwo = new Runnable() {
            @Override
            public void run() {
                frame.setSize(800, 600);
                frame.setVisible(true);
                button1.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent arg0) {
                        runone.run();
                        System.out
                                .println("This is performed, but the button doesnt change");
                    }
                });
                frame.add(button1);
            }
        };
        runtwo.run();
    }
}
4

2 回答 2

4

没有什么特别的东西Runnable可以阻止它工作。正如您的代码示例所代表的那样,以下内容是等效的:

public void actionPerformed(ActionEvent arg0) {
    runone.run();
    System.out.println("This is performed, but the button doesnt change");
}

public void actionPerformed(ActionEvent arg0) {
    frame.removeAll();
    frame.revalidate();
    frame.repaint();
    frame.add(button2);
    System.out.println("This is performed, but the button doesnt change");
}

获取您的代码并System.out.println在其中添加调试语句runone.run表明它实际上正在执行。

我假设您的代码示例旨在简化您的问题的演示;您可能希望首先考虑让它作为“普通功能”执行您想要的操作(我上面的第二个示例,其中 Runnables 组合在一起),然后分离成不同的 Runnables。

编辑-为了使您的示例正常工作,要记住的是JFrame使用 contentPane 来托管其子项-frame.add存在是为了方便添加到 contentPane(基于JFrame 的 javadoc),但removeAll不这样做(基于我玩现在就用它)。此外,在添加按钮后调用validate将再次正确重新布局子组件以显示第二个按钮。

用这个替换您的定义runone,您的示例将起作用:

runone = new Runnable() {
    @Override
    public void run() {
        frame.getContentPane().removeAll();
        frame.add(button2);
        frame.validate();
    }
};
于 2012-12-26T20:40:32.240 回答
3

您应该首先将对象封装Runnable在一个Thread对象中,然后通过调用start(). 例如:

Runnable r = ...;
Thread thread = new Thread(r);
thread.start();


编辑:

您应该确保从 EDT 调用 Runnable。例如:

SwingUtilties.invokeLater(r);

或者,您可能会使用它SwingWorker来处理与 swing 代码相关的密集操作。请参阅此答案以了解 SwingWorker 的工作原理。

于 2012-12-26T20:05:08.997 回答