Java 正在等待组件的IsDisployable
在测试游戏时,我有时会在组件不可显示时引发异常。我在isDisplayable()上添加了一个等待循环 似乎我的游戏需要几百毫秒才能显示出来 这是处理这个问题的明智方法吗 我正在测试通过套接字与服务器对话的游戏客户端 谢谢 编辑1:谢谢你的评论。我发现在gui完成构建和初始化之前,我正在将gui的中介(观察者)添加到模型(可观察者)中。更糟糕的是,我正在初始化一个面板,调用createImage返回null并抛出Java 正在等待组件的IsDisployable,java,swing,invokelater,Java,Swing,Invokelater,在测试游戏时,我有时会在组件不可显示时引发异常。我在isDisplayable()上添加了一个等待循环 似乎我的游戏需要几百毫秒才能显示出来 这是处理这个问题的明智方法吗 我正在测试通过套接字与服务器对话的游戏客户端 谢谢 编辑1:谢谢你的评论。我发现在gui完成构建和初始化之前,我正在将gui的中介(观察者)添加到模型(可观察者)中。更糟糕的是,我正在初始化一个面板,调用createImage返回null并抛出 import java.awt.*; import javax.swing.*;
import java.awt.*;
import javax.swing.*;
public class WaitForFrameToBeVisible {
JFrame frame=new JFrame("FrameDemo");
private void createAndShowGUI() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel emptyLabel=new JLabel("");
emptyLabel.setPreferredSize(new Dimension(175,100));
frame.getContentPane().add(emptyLabel,BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
void run() throws Exception {
System.out.println("waiting for frame to be displayable");
long t0=System.nanoTime();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
while (!frame.isDisplayable())
Thread.sleep(1);
long dt=System.nanoTime()-t0;
System.out.println("waited "+dt/1_000_000.+" ms. for frame to be displayable");
}
public static void main(String[] args) throws Exception {
new WaitForFrameToBeVisible().run();
}
}
您不需要使用
isDisplayable()
。您可以使用invokeAndWait(…)
来执行以下操作:
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createAndShowGUI();
}
});
// control will reach here when the GUI will be created
请注意,通过这种方式,您实际上并不是在检查框架是否可见,而是在检查createAndShowGUI()是否已完成其工作
另一件事是您不应该在循环中调用isDisplayable()
或任何类似的函数。这将消耗不必要的处理速度。而是使用wait notify
但就您的案例而言,使用
WindowListener
是一个非常好的主意,正如在评论中所建议的那样。我会“猜测”您在Swing API构建和验证UI和尝试更新UI之间存在线程争用情况,但这很难说。不,就我个人而言,这不是解决问题的明智方法,Swing不是线程安全的,所以你冒着不同比赛条件的风险。我想尝试的是使用<代码> Windows WistListor ,并注意可见性的变化,但是您必须进一步测试100%个步骤,为什么在一个不是Swing /AWT线程的线程中做Swing的东西?也许还是等着吧?我正在测试通过套接字与服务器对话的游戏客户端。@RayTayek不太可能,组件“可显示”(通过帧的pack
和setVisible
)之前可以修改层次结构。实际上,很难保证组件是可显示的,因为这在很大程度上取决于底层操作系统的实现。通常,我使用WindowListener
,当窗口可见时,使用invokeLater
只是为了“更”确定我可以对组件进行所需的更改。记住,Swing不是线程安全的,切勿尝试更改或检查EDT上下文外部组件的状态等待invokeAndWait
返回不会保证帧可见或可显示,因为该过程可能会生成其他事件,这些事件会在createAndShowGUI
完成后添加到EDT(并且invokeAndWait
已返回)-这只是另一个竞争条件我想我在编写代码后解释过。但是,你甚至不应该费心提及它,它并没有真正解决问题,并引入了另一个可能的竞争条件。就像你永远不应该在EDT上下文之外修改组件一样,你永远不应该查询组件的状态我也是,因为这只是一个诱人的比赛条件:P