JAVA - how to modify SWT UI while looping in thread
JAVA - how to modify SWT UI while looping in thread
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?
1 Answer
1
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.
Thread
Display.asyncExec
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.
SwingUtilities
You can also use the timerExec
method of Display
to run code after a specific delay which avoids the need for a background thread.
timerExec
Display
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);
}
});
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
yep, that was it. thanks a lot @greg-449 !
– Daniel S
Jul 1 at 8:31