Reputation: 609
I'm trying to implement a Desktop app that loops trough a function and sets a textfield on the UI every 1 sec.
But I either get
org.eclipse.swt.SWTException: Invalid thread access
when I don't use the display
or the UI is really sluggish when I do
display.asyncExec(new Runnable() {
My code looks like this:
public void open() {
Display display = Display.getDefault();
shell = new Shell();
shell.setSize(486, 322);
shell.setText("SWT Application");
Button btnStartLoop = new Button(shell, SWT.NONE);
btnStartLoop.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
SwingUtilities.invokeLater(new Runnable() {
public void run() // updates displayArea
{
while (true) {
try {
text.setText("Text has been set");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
}
});
btnStartLoop.setBounds(35, 30, 75, 25);
btnStartLoop.setText("Start Loop");
text = new Text(shell, SWT.BORDER);
text.setText("0");
text.setBounds(116, 32, 177, 21);
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
is there any way this can be overcome?
Upvotes: 0
Views: 315
Reputation: 111142
You must never sleep in the UI thread. You must use a new Thread
for the background activity. You call Display.asyncExec
from within the thread to run the UI update code in the UI thread.
btnStartLoop.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent e) {
final Thread background = new Thread(new Runnable() {
public void run()
{
while (true) {
try {
Display.getDefault().asyncExec(() -> text.setText("Text has been set"));
Thread.sleep(1000);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
});
background.start();
}
});
Note: SwingUtilities
is for Swing applications, do not use it in SWT apps.
You can also use the timerExec
method of Display
to run code after a specific delay which avoids the need for a background thread.
btnStartLoop.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(final MouseEvent e) {
final Runnable update = new Runnable() {
public void run()
{
text.setText("Text has been set");
Display.getDefault().timerExec(1000, this);
}
};
Display.getDefault().timerExec(0, update);
}
});
Upvotes: 2