The second hand is drawn with a redraw()
on the Canvas
, but this will need to be run periodically. If it is redrawn once per second, it can emulate a clock ticking.
Eclipse has a mechanism called jobs
which would be just right for this task, but these will be covered in Chapter 4, Interacting with the User. So to begin with, a simple Thread
class will be used to issue the redraw.
ClockView
class.createPartControl()
method:new Thread("TickTock") { public void run() { while (!clock.isDisposed()) { clock.redraw(); try { Thread.sleep(1000); } catch (InterruptedException e) { return; } } } }.start();
When the Clock View is created, a Thread
is created and started, which runs once per second. Every second, in the host Eclipse instance's Console View, an exception is generated that looks like this:
Exception in thread "TickTock" org.eclipse.swt.SWTException: Invalid thread access at org.eclipse.swt.SWT.error(SWT.java:4361) at org.eclipse.swt.SWT.error(SWT.java:4276) at org.eclipse.swt.SWT.error(SWT.java:4247) at org.eclipse.swt.widgets.Widget.error(Widget.java:775) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:570) at org.eclipse.swt.widgets.Control.redraw(Control.java:2748) at com.packtpub.e4.clock.ui.views.ClockView$2.run(ClockView.java:41)
This is expected behavior in this case, but it's worth taking a dive into the SWT internals to understand why.
Many windowing systems have a UI thread which is responsible for coordinating the user interface updates with the program code. If long running operations execute on the UI thread, the program can appear to hang and become unresponsive. Many windowing systems will have an automated process, which changes the cursor into an hourglass if the UI thread for an application is blocked for more than a short period of time.
SWT mirrors this by providing a UI thread for interacting with the user interface, and ensures that updates to SWT components are done on this thread. Redraws occur on the SWT thread, as do calls to methods like createPartControl()
.
In the clock update example, updates are being fired on a different thread (in this case, the TickTock
thread) and it results in the preceding exception. So how are these updates run on the right thread?