How to disable a Button from being active after press?

SWT Designer allows you to create the views, editors, perspectives, pref pages, composites, etc. that comprise Eclipse SWT & RCP applications and plug-ins.

Moderators: Konstantin.Scheglov, gnebling, Alexander.Mitin, jwren, Eric Clayberg

How to disable a Button from being active after press?

Postby Samiad » Mon Apr 26, 2010 12:54 am

Hi,

I have a (hopefully simple) problem to overcome. If I have a Button that executes a potentially long running method, how can I disable successive presses of that button?

I have hooked into the SelectionListener to first disable the Button, then do the work, followed by re-enabling the Button on its return. However it seems that once the Button becomes disabled I can actually click the button once more and it 'queues' up the selection event until after the first SelectionEvent is finished.

I've taken some demo code to present the scenario. The Button starts a Thread.sleep(5000), and even though my Button is disabled it seems it will still queue up SelectionEvents for processing immediately afterwards.

Code: Select all
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;


public class Main
{
    static Text text;
    static Button b;

   public static void main(String[] args)
   {
       Display display = new Display();
       Shell shell = new Shell(display);
       GridLayout layout = new GridLayout();
       layout.numColumns = 2;
       layout.makeColumnsEqualWidth = true;
       shell.setLayout(layout);
      
       GridData data = new GridData(GridData.FILL_BOTH);
       b = new Button(shell, SWT.PUSH);
       b.setText("Push Me");
       b.setLayoutData(data);
       b.addSelectionListener(new SelectionAdapter()
       {
           public void widgetSelected(SelectionEvent event)
           {
               text.append("Testing Thread Update\n");
               b.setEnabled(false);
               try
               {
                   Thread.sleep(5000);
               }
               catch(Exception e)
               {
                  
               }
               text.append("Added something else\n");
               b.setEnabled(true);
           }
          
       });
      
       data = new GridData(GridData.FILL_BOTH);
       text = new Text(shell, SWT.MULTI | SWT.V_SCROLL | SWT.WRAP);
       text.setLayoutData(data);
      
      
       shell.pack();
       shell.open();
       while(!shell.isDisposed())
       {
           if (!display.readAndDispatch())
           {
               display.sleep();
           }
       }
       display.dispose();   
   }
}


Thanks for any advice - the SWT Designer has proven to be a fantastic aid.
Samiad
 
Posts: 3
Joined: Thu Apr 22, 2010 11:53 pm

Re: How to disable a Button from being active after press?

Postby Alexander.Mitin » Mon Apr 26, 2010 5:05 am

You have to use a separated thread or async operation for long-running operations.
SWT uses native event loop and you can't do 'setEnabled' in click listener.
For example, under Windows it looks like (other supported OS'es have a similar behaviour):
1. User clicks the Button.
2. OS sends WM_CLICK message to the button window.
3. SWT hooks this message and calls your click listener.
4. You invoke 'setEnabled' in your listener. Note, that you still are in WM_CLICK message handler.
5. SWT issues WM_ENABLE message and passes it to the OS.
6. The OS adds the WM_ENABLE message into the OS event queue.
7. Because the button window is in process of handling WM_CLICK message, the WM_ENABLE message would be handled later.

For example, modify the code of your listener like this:
Code: Select all
      b.addSelectionListener(new SelectionAdapter() {
         public void widgetSelected(SelectionEvent event) {
            text.append("Testing Thread Update\n");
            b.setEnabled(false);
            Display.getCurrent().asyncExec(new Runnable() {
               public void run() {
                  try {
                     Thread.sleep(5000);
                  } catch (Exception e) {
                  }
                  text.append("Added something else\n");
                  b.setEnabled(true);
               }
            });
         }
      });

Note, such async operation would freeze the entire UI because it uses same OS event queue as user's message. The preferred way is to implement long processing as a separated thread.

Also note that general SWT questions like this should be posted to the Eclipse SWT newsgroup.
Alexander Mitin
Alexander.Mitin
Moderator
 
Posts: 155
Joined: Fri Jan 19, 2007 3:57 am

Re: How to disable a Button from being active after press?

Postby Samiad » Mon Apr 26, 2010 8:14 am

Thanks Alexander, point taken regarding location for the topic.
Samiad
 
Posts: 3
Joined: Thu Apr 22, 2010 11:53 pm

Re: How to disable a Button from being active after press?

Postby Eric Clayberg » Mon Apr 26, 2010 10:46 am

Glad we could help.
Eric Clayberg
Software Engineering Manager
Google
http://code.google.com/webtoolkit/download.html

Author: "Eclipse Plug-ins"
http://www.qualityeclipse.com
Eric Clayberg
Moderator
 
Posts: 4503
Joined: Tue Sep 30, 2003 6:39 am
Location: Boston, MA USA


Return to SWT Designer

Who is online

Users browsing this forum: Google [Bot] and 2 guests