我正在尝试让我的Blackberry应用程序显示自定义模式对话框,并让开始线程等到用户关闭对话框屏幕。
final Screen dialog = new FullScreen();
...// Fields are added to dialog
Application.getApplication().invokeAndWait(new Runnable()
{
public void run()
{
Application.getUiApplication().pushModalScreen(dialog);
}
});
这是抛出一个Exception,它说“由非事件线程调用pushModalScreen”,尽管我使用invokeAndWait从事件线程调用pushModalScreen。
关于真正问题是什么的任何想法?
以下是复制此问题的代码:
package com.test;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public class Application extends UiApplication {
public static void main(String[] args)
{
new Application();
}
private Application()
{
new Thread()
{
public void run()
{
Application.this.enterEventDispatcher();
}
}.start();
final Screen dialog = new FullScreen();
final ButtonField closeButton = new ButtonField("Close Dialog");
closeButton.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
Application.getUiApplication().popScreen(dialog);
}
});
dialog.add(closeButton);
Application.getApplication().invokeAndWait(new Runnable()
{
public void run()
{
try
{
Application.getUiApplication().pushModalScreen(dialog);
}
catch (Exception e)
{
// To see the Exception in the debugger
throw new RuntimeException(e.getMessage());
}
}
});
System.exit(0);
}
}
我正在使用组件包版本4.5.0。
答案 0 :(得分:2)
基于Max Gontar观察到在使用invokeLater而不是invokeAndWait时没有抛出Exception,完整的解决方案是从invokeLater和Java的同步方法中正确实现invokeAndWait:
public static void invokeAndWait(final Application application,
final Runnable runnable)
{
final Object syncEvent = new Object();
synchronized(syncEvent)
{
application.invokeLater(new Runnable()
{
public void run()
{
runnable.run();
synchronized(syncEvent)
{
syncEvent.notify();
}
}
});
try
{
syncEvent.wait();
}
catch (InterruptedException e)
{
// This should not happen
throw new RuntimeException(e.getMessage());
}
}
}
不幸的是,无法覆盖invokeAndWait方法,因此必须小心地调用此静态版本。
答案 1 :(得分:2)
似乎那里有许多代码是不必要的。
public class Application extends UiApplication {
public static void main(String[] args)
{
new Application().enterEventDispatcher();
}
private Application()
{
final Screen dialog = new FullScreen();
final ButtonField closeButton = new ButtonField("Close Dialog");
closeButton.setChangeListener(new FieldChangeListener()
{
public void fieldChanged(Field field, int context)
{
Application.getUiApplication().popScreen(dialog);
}
});
dialog.add(closeButton);
// this call will block the current event thread
pushModalScreen(dialog);
System.exit(0);
}
}
答案 2 :(得分:0)
使用此:
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
pushScreen(new MyScreen());
}
});