问题描述
在运行以下代码时,我目前遇到一些麻烦。如果删除此部分,问题将消失,因此整个代码的这一部分必定是问题。它运行并绘制出我想要的东西,但是几秒钟后(通过用户(毫秒)设置了maxAddedRuntime),应用程序冻结了一段时间(窗口没有响应Windows消息),并在等待大约相同的时间后重新开始绘制窗口被冻结。我做错了什么? 我正在使用SWT和画布进行绘制。谢谢您的帮助
public void drawNetwork(Canvas canvas,GC gc,Network network,Shell shlNetworkVisualizer) {
startTime = System.currentTimeMillis();
endTime = startTime + maxAddedRuntime;
this.drawNetworkAlg1(canvas,gc,network);
int canvasHeight = canvas.getBounds().height;
int canvasWidth = canvas.getBounds().width;
while (System.currentTimeMillis()<endTime) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
gc.fillRectangle(0,canvasWidth,canvasHeight); //ClearCanvas basically
for (Nodek: network.node) {
//drawSomeStuff
}
for (Edge k: network.edges) {
//alsoDrawSomeStuff
}
}
}
解决方法
SWT应用程序必须尽快返回主Display.readAndDispatch
循环。因此,您不能使用带有Thread.sleep
调用的循环-这只会锁定UI,直到循环结束。
相反,您可以在延迟后使用Display.timerExec
来运行代码。您可以使用它来执行一个步骤(例如,仅执行一个gc.fillRectange),然后再次调用Display.timerExec
来安排下一步。
public void timerExec(int milliseconds,Runnable runnable)
注意:您从绘制事件中收到的GC仅在绘制期间有效。通常,timerExec调用应该只在画布上调用redraw
才能引起新的绘制事件的产生。
这是一个简单的类,它执行基本的timerExec调用和绘制:
class Progress
{
private final Canvas canvas;
private final long endTime;
Progress(Canvas c)
{
canvas = c;
endTime = System.currentTimeMillis() + 1_000;
canvas.addListener(SWT.Paint,this::paint);
canvas.getDisplay().timerExec(100,this::timer);
}
private void paint(Event event)
{
GC gc = event.gc;
int canvasHeight = canvas.getBounds().height;
int canvasWidth = canvas.getBounds().width;
gc.fillRectangle(0,canvasWidth,canvasHeight);
// TODO more painting
}
private void timer()
{
if (canvas.isDisposed()) { // Don't continue if control closed
return;
}
canvas.redraw();
if (System.currentTimeMillis() < endTime) {
canvas.getDisplay().timerExec(100,this::timer);
}
}
}