I have following class.
- Why the
btnDecorateis allways enabled? I wanted to disable the button when the loop is under processing. - Why
text.redraw()works only in the end of loop? I wanted to see the box sequently on every character.
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
public class SampleRefreshStyledText {
public static void main(String[] args) {
final Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout(SWT.VERTICAL));
final Button btnDecorate = new Button(shell, SWT.NONE);
btnDecorate.setText("Decorate");
final StyledText text = new StyledText(shell, SWT.NONE);
text.setText("ABCDEFGHIJKLMNOPRQ\n1234567890");
btnDecorate.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent event) {
btnDecorate.setEnabled(false);
for (int i = 0; i < text.getText().length(); i++) {
StyleRange styleRange = new StyleRange();
styleRange.start = i;
styleRange.length = 1;
styleRange.borderColor = display.getSystemColor(SWT.COLOR_RED);
styleRange.borderStyle = SWT.BORDER_SOLID;
styleRange.background = display.getSystemColor(SWT.COLOR_GRAY);
text.setStyleRange(null);
text.setStyleRange(styleRange);
text.redraw();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
btnDecorate.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent arg0) {}
});
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) display.sleep();
}
display.dispose();
}
}
You can't write loops like this with SWT.
All UI operations occur on the single UI thread. Calling
Thread.sleepputs the UI thread to sleep and nothing at all will happen.The
redrawcall only requests that the text is redrawn, it will not actually happen until the next time thedisplay.readAndDispatch()is run, so doing this repeatedly in a loop doesn't work.What you have to do is run the first step of your loop once. You must then arrange to run the next step 500ms later without blocking the thread. You can do this using the
Display.timerExecmethod to request that code is run at a later time:where
runnableis a class implementingRunnablethat does the next step. At the end of this code you calltimerExecagain until you have worked your way through all the steps.