Reputation: 41
I am currently having some trouble when running the follwing code. If I delete this part the problems disappear so this part of my whole code has to be the problem. It runs and draws what I want perfectly but after a few seconds (maxAddedRuntime is set via user (milliseconds)) the application freezes for a while (window is not responding Windows message) and starts over with drawing after waiting approximately the same time while the window is frozen. What do I do wrong? I am using SWT and a canvas to draw. Thank you for your help
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, 0, canvasWidth, canvasHeight); //ClearCanvas basically
for (Nodek: network.node) {
//drawSomeStuff
}
for (Edge k: network.edges) {
//alsoDrawSomeStuff
}
}
}
Upvotes: 1
Views: 408
Reputation: 111142
An SWT app must return to the main Display.readAndDispatch
loop as quickly as possible. So you cannot use a loop with a Thread.sleep
call - this will just lock up the UI until the loop ends.
Instead you can use Display.timerExec
to run code after a delay. You would use this to run a single step (just one gc.fillRectange for example) and then call Display.timerExec
again to schedule the next step.
public void timerExec(int milliseconds, Runnable runnable)
Note: The GC you receive from a paint event is only valid during the paint. The timerExec call should normally just call redraw
on the canvas to cause a new paint event to be generated.
Here is a simple class that does basic timerExec calls and paints:
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, 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);
}
}
}
Upvotes: 3