繁体   English   中英

从另一个Runnable内部运行Runnable的Java将无法运行

[英]Java running a Runnable from inside another Runnable won't work

为什么以下代码不起作用? 基本上,这是一个难度较大的程序的简化版本,在该程序中,我试图创建一个具有所选内容的可运行初始屏幕,然后将这些按钮具有链接到不同可运行对象的按钮,但此操作未达到我的预期。

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();
    }
}

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

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

我假设您的代码示例是您问题的简化演示; 您可能想研究如何使其首先作为“纯函数”(上面的第二个示例,其中合并了Runnable)来完成您想要的事情,然后将其分成不同的Runnable。

编辑 -为了使您的示例正常工作,要记住的事情是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();
    }
};

您应该首先将 Runnable对象封装在 Thread对象中,然后通过调用 start()启动线程。 例如:

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


编辑:

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

SwingUtilties.invokeLater(r);

或者您可以使用SwingWorker来处理与swing代码有关的密集操作。 查看此答案以了解SwingWorker的工作方式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM