Question

I know many people experience this problem, but the solutions I found online do not seem to solve mine. I have a composite that has three buttons. What I want is the following : When I click one button, I want some other button to be grayed out ( setEnabled(false) ) and after a while (after a method execution), I want the button to be enabled again.

Many such problems are solved by calling layout() method on the parent container, or this very similar one is solved by calling Display.getCurrent().update();

Simply, my code could be summarized as follows :


import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;


public class app1 {

    protected Shell shell;

    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {
        try {
            app1 window = new app1();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    Button button1 , button2 , button3;
    Label label;
    protected void createContents() {
        shell = new Shell();
        shell.setSize(450, 300);
        shell.setText("SWT Application");
        shell.setLayout(new GridLayout(1,false));
        {
            final Composite composite = new Composite(shell, SWT.NONE);
            composite.setLayout(new GridLayout(3,false));
            GridData gd_composite = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
            gd_composite.grabExcessHorizontalSpace = true;          
            gd_composite.horizontalSpan = 10;   //?
            gd_composite.verticalIndent = 5;
            composite.setLayoutData(gd_composite);
            GridData gd_button;

            {
                button1 = new Button(composite, SWT.NONE);
                button1.setText("Button 1");
                gd_button = new GridData(SWT.FILL, GridData.BEGINNING, false, false);
                gd_button.horizontalSpan = 1;
                button1.setLayoutData(gd_button);
                button1.addSelectionListener(new SelectionListener(){
                    public void widgetSelected(SelectionEvent e){
                        try{
                        button2.setEnabled(false);
                        button2.redraw();
                        button2.update();

                        //composite.redraw();
                        //composite.update();
                        //composite.layout();

                        shell.redraw();
                        shell.update();
                        shell.layout();                     
                        Display.getCurrent().update();
                        }   catch   (Exception e2)  {
                            System.err.println("exception e : " + e2.toString());
                        }

                        System.out.println("basla");


                        try {
                            System.out.println("sleep1");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }
                        try {
                            System.out.println("sleep2");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }
                        try {
                            System.out.println("sleep3");
                            Thread.sleep(100);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }   catch (Throwable th)    {
                            System.err.println("th: " + th.toString());
                        }

                        for(int i=0 ; i < 10000 ; i++)
                        {
                            System.out.println(i);
                        }
                    }
                    public void widgetDefaultSelected(SelectionEvent e) {
                        System.err.println("widgetDefault !");
                    }
                });
            }
            {
                button2 = new Button(composite, SWT.NONE);
                button2.setText("Button 2");
                gd_button = new GridData(SWT.FILL, GridData.CENTER, false, false);
                gd_button.horizontalSpan = 1;
                button2.setLayoutData(gd_button);
                button2.addSelectionListener(new SelectionListener(){
                    public void widgetSelected(SelectionEvent e){
                        button1.setEnabled(false);
                        composite.layout();
                        for (int i=1; i<=100; i++) {
                             try {
                                  Thread.sleep(10);
                             } catch (Throwable th) {}
                            label.setText(i + " %");
                            label.update();
                        }
                    }
                    public void widgetDefaultSelected(SelectionEvent e) {}
                });
            }

            {
                label = new Label(composite , SWT.NONE);
                label.setText("0 %");
                label.update();
            }
        }
    }
}

What happens is, the button gets disabled after the end of widgetSelected() method is reached. However, the label gets updated frequently without any problem (even when the label.update() method is not there)

Additional information : Say, I disable the button, then put a Thread.sleep() and then enable the button ; it sleeps first and then quickly disables and enables the button. So I believe all such paint requests are queued and are processed at the end of the execution.

Useful information: I realized that, when I create and display a MessageBox right after my display changes, the display changes occur. So, if I make the following change in my widgetSelected method :


button2.setEnabled(false)
MessageBox mBox = new MessageBox(Display.getCurrent().getActiveShell(), SWT.ICON_INFORMATION | SWT.OK);
mBox.setText("Information");
mBox.setMessage("Buttons updated!");
mBox.open();

the button will be grayed out as soon as the widgetSelected() method is called. This makes me believe my solution lies within Display.getCurrent() methods. However, I tried

Display.getCurrent().getActiveShell().redraw()
Display.getCurrent().getActiveShell().update()
Display.getCurrent().getActiveShell().layout() 

methods and they didnt solve my problem.

Thanks, Ege

Was it helpful?

Solution

Ok, i've corrected the answer from ginu:

New Runnable().run() does actually not much to nothing, but the idea is correct:

You need a new thread to do your work in. Problem is, from that thread you can't call setEnabled on the buttons, because that can only be done from within the SWT-Event thread.

So you need another runnable to reset the buttons. The second runnable is passed to Display.callAsync and returns before it is actually executed, but that doesn't matter here. You could also use Display.callSync( Runnable ), that call would block your calling thread until the runnable returns.

Tested it in Eclipse, looks good so far.

Edit: Btw, the reason why calling layout() or Display.update() did not work is that you're currently blocking the SWT-Thread with your work, so the calls to layout/update are queued and only executed when you leave the event handler. Never block an event handler to do long work. :)

package test;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Test {

public static void main(final String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setLayout(new GridLayout(3, false));
    final Button button1 = new Button(shell, SWT.PUSH);
    button1.setText("Click");
    final Button button2 = new Button(shell, SWT.PUSH);
    button2.setText("Me");
    final Button button3 = new Button(shell, SWT.PUSH);
    button3.setText("Dude");

    button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
    button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));

    button2.setEnabled(false);
    button3.setEnabled(false);

    button1.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(final SelectionEvent e) {
            button1.setEnabled(false);
            button2.setEnabled(true);
            button3.setEnabled(true);

            new Thread( new Runnable() {
                public void run() {
                    try {
                        // Do your operation here.
                        //
                        // Dummy sleep performed here instead.
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    shell.getDisplay().asyncExec( new Runnable() {
                        public void run() {
                          button1.setEnabled(true);
                          button2.setEnabled(false);
                          button3.setEnabled(false);
                        }
                    });
                }
            } ).start();
        }
    });

    shell.open();
    shell.pack();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }

}

}

OTHER TIPS

It doesn't appear that your snippet is complete, but a few things came to mind regarding your problem. You can probably use setEnabled as seen in the snippet below. For more advance things you could look at GridLayout and GridData with the .exclude property in conjunction with setVisible. For reference the SWT Snippets page is really great.

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class App2 {

    public static void main(final String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(3, false));
        final Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("Click");
        final Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("Me");
        final Button button3 = new Button(shell, SWT.PUSH);
        button3.setText("Dude");

        button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setEnabled(false);
        button3.setEnabled(false);

        button1.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(true);
                button3.setEnabled(false);
            }
        });

        button2.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(false);
                button3.setEnabled(true);
            }
        });

        button3.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(true);
                button2.setEnabled(false);
                button3.setEnabled(false);
            }
        });

        shell.open();
        shell.pack();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

    }
}

I am not really sure if you have a problem with the enabling / disabling of the buttons, or putting the delay in between the execution flow.

I have modified Jared's code above to perform both these operations mentioned. Please have a look at this and let me know if this what you were looking for.

Cheers. :-)

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class app1 {

    public static void main(final String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new GridLayout(3, false));
        final Button button1 = new Button(shell, SWT.PUSH);
        button1.setText("Click");
        final Button button2 = new Button(shell, SWT.PUSH);
        button2.setText("Me");
        final Button button3 = new Button(shell, SWT.PUSH);
        button3.setText("Dude");

        button1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
        button3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));

        button2.setEnabled(false);
        button3.setEnabled(false);

        button1.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                button1.setEnabled(false);
                button2.setEnabled(true);
                button3.setEnabled(true);

                new Runnable() {
                    public void run() {

                        try {
                            // Do your operation here.
                            //
                            // Dummy sleep performed here instead.
                            Thread.sleep(1000);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }

                    }
                }.run();

                button1.setEnabled(true);
                button2.setEnabled(false);
                button3.setEnabled(false);
            }
        });

        shell.open();
        shell.pack();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top