2012-12-26 35 views
2

为什么下面的代码不起作用?基本上,这是一个更困难的程序的简化版本,我在其中尝试创建一个可运行的初始屏幕,然后将选择按钮链接到不同的可运行的按钮,但这并不像我预期的那样运行。从另一个Runnable中运行Runnable的Java将不起作用

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

您是否尝试过在你的第一个可运行来验证添加调试语句?正如所写的,它只是一个直接的函数调用,没有什么特别的... – Krease

回答

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

以你的代码,并添加内runone.run一个System.out.println调试声明表明,它实际上是在执行。

我假设你的代码示例是一个简化的问题演示;你可能希望首先考虑让它做一个你想做的'纯函数'(我的第二个例子,Runnables被合并),然后分离成不同的Runnables。

编辑 - 让您的示例工作,需要记住的是,JFrame使用的contentPane主办的孩子 - frame.add存在为方便添加到contentPane(基于javadoc for JFrame),但removeAll不会这样做(基于我刚刚玩它)。此外,在添加按钮后调用validate将再次正确地重新布局子组件,让您的第二个按钮出现。

与此一替换您的runone定义,您的样品将工作:

runone = new Runnable() { 
    @Override 
    public void run() { 
     frame.getContentPane().removeAll(); 
     frame.add(button2); 
     frame.validate(); 
    } 
}; 
+0

所以这是我小的情况下,正确的解决方案,但我更大的情况下,从几个按钮,然后在窗口中所做的每个按钮导致游戏(在不同的语言),不runnable.run工作是()或SwingUtilities.InvokeLater(runnable); –

+0

尝试在调试器中逐步完成它 - Runnables中的语句将被执行(只需添加断点或调试语句来证明它);他们内部的陈述的正确性通常很重要。一个好的调试器将帮助您更清楚地看到代码流,并帮助您关注各个状态的状况以及可能出错的地方。 – Krease

3

你应该先封装一个 Thread对象中的 Runnable对象,然后通过调用 start()启动你的线程。例如:

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


编辑:

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

SwingUtilties.invokeLater(r); 

或者你可以使用SwingWorker对付了涉及摆动代码密集型操作。了解SwingWorker的工作方式,请参阅this answer

+0

你能举一个简短的例子吗? –

+0

@ user268396我更新了我的答案。请看看它。 –

+0

改变你的答案,线程谈话只会掩盖有效点。 – user268396