Link to home
Start Free TrialLog in
Avatar of rubentrancoso
rubentrancoso

asked on

JToggle disabled after popup hide

Hello experts,

I´m trying to do that a JToggleButton raises a popup and it must be hided in tree ways. First clicking in a menu option, deselecting the JToggleButton or clicking outside the popup and button.
What is happening is that I´m not reaching the right way to control it. I´m using a ActionListener to get ToggleButton events and a PopupMenuListener to change the JToggleButton state when it hides, but I´m having indesireable behaviors in the togglebutton when I click on it to hide the popup cause the hide event changes de button state to unselected than it generate the action event like I´m opening the menu again.

Some idea?



Avatar of gnoon
gnoon
Flag of Thailand image

Sounds like having more than 1 controller to control the JToggleButton state:

- mouse click on the button

  mouse click on the button --> button state change --> actionPerformed--> popup visible

- PopupMenuListener

  popup hiding --> popupMenuWillBecomeInvisible --> button state change (above) --> ...

Is this current behaviors?

If yes, you should code for checking which source generates event in actionPerformed, or using the JToogleButton state to decide popup visible.
Avatar of Mick Barry
can u post your code (in particular your action listener)
Avatar of rubentrancoso
rubentrancoso

ASKER

Sure,
here is the code!
I´ll make a new executable class to post here, for now the code is mixed and it will take more time.

===================================

            JToggleButton tb = new JToggleButton("ShowPopup");

            tb.addActionListener(
                  new ActionListener() {
                        public void actionPerformed( ActionEvent e ) {
                              JToggleButton b = ((JToggleButton)e.getSource());
                              boolean selected = b.isSelected();
                              if ( selected ) {
                                     showPopupUp();
                              }
                        }
                  }
            );


==========================================================

        popupMenu.addPopupMenuListener(
                    new PopupMenuListener( ) {
                          public void popupMenuCanceled( PopupMenuEvent e ) {
                          }
                          public void popupMenuWillBecomeVisible( PopupMenuEvent e ) {
                          }
                          public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) {
                                tb.setSelected(false);
                          }
                    }
        );
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
a better sample...

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

public class ToggleControl extends JFrame {
   
    MyPopup cp;
    JToggleButton tb;    
   
    public ToggleControl() {
        this.addWindowListener(
            new WindowAdapter() {
                public void windowClosing( WindowEvent e ) {
                    System.exit(0);
                }
            }
        );
        this.setSize( 500, 500 );
        this.setVisible(true);
        this.setLayout( new FlowLayout() );
        cp = new MyPopup();
       
        cp.addPopupMenuListener(
                new PopupMenuListener( ) {
            public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
            }
            public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
                                      tb.setSelected(false);
            }
            public void popupMenuCanceled(PopupMenuEvent arg0) {
            }
                }
        );        
       
        tb = new JToggleButton("Start");
        this.getContentPane().add(tb);
        this.validate();
       
        tb.addActionListener(
                new ActionListener() {
                     public void actionPerformed( ActionEvent e ) {
                          JToggleButton b = ((JToggleButton)e.getSource());
                          boolean selected = b.isSelected();
                          if ( selected ) {
                                cp.show( tb, tb.getWidth(), tb.getHeight() );
                          }
                     }
                }
           );
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ToggleControl tc = new ToggleControl();
    }
   
    class MyPopup extends JPopupMenu {
       
        static final int SIDEBARWIDTH = 20;
       
        public MyPopup() {
            JMenu m = new JMenu("SubMenu");
            JMenuItem mi = new JMenuItem("SubItem 1");
            m.add(mi);
            mi = new JMenuItem("SubItem 2");
            m.add(mi);
            this.add( m );
            mi = new JMenuItem("Item 1");
            this.add( mi );
            mi = new JMenuItem("Item 2");
            this.add( mi );
        }
       
        public void show( Component c, int x, int y ) {
            super.show( c, x, y );
        }
    }

}
the main problem is when the popup is allready open and I try to unselect the toggle clicking on it.
But the popup event change de button after hide and what happens is that the buttons goes pressed again and the popup appears.
yes I realise that. It is occurring because when the ActionEvent gets prcoessed the toggle button is unselected.
Did u try the code I posted?
yes, the same behavior
Use tb.doClick(); in popupMenuWillBecomeInvisible() instead. It should works.
As JavaDoc (http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/AbstractButton.html#setSelected(boolean)),

 " public void setSelected(boolean b)
      Sets the state of the button. Note that this method does not trigger an actionEvent. Call doClick to perform
      a programatic action change. "

Because of  JToogleButton.setSelected() method does not trigger an actionEvent, the JToggleButton state isn't changed but only its color. So, the b.isSelected() in actionPerformed always returns true while clicking on the button.
>  the JToggleButton state isn't changed but only its color.

no, the button state is changed.
Sorry, my foolish ;-)
I thinking that I must add a glasspane to control de button behavior. Not sure.
how would a glass pane help exactly?
rubentrancoso, how about tb.doClick()? did you try?
I can intercept the click on it ( glasspane ) and make the action myself. ( i think )
The big trouble is that ever the togglebutton raises a action the button state is allready set to the new value ( selected oe deselected ). When I click over the button what first happen is the popupevent deselecting the button, and after that, the action event is processed normaly and independently.
With the doclick it just deselect the button before the click happens over the button. When the click occours out of the button it is tha same as seting the button deselected.
I´m not seeing how to mix this two paths.
> I can intercept the click on it ( glasspane ) and make the action myself. ( i think )

then why use a button at all?

> When I click over the button what first happen is the popupevent deselecting the button, and after that, the action event is processed normaly and independently.

yes, I mentioned that earlier

> I´m not seeing how to mix this two paths.

Not sure you easily can.
maybe, but I tried to get the mouse position eg but when the popup gos hide there´s no way to now the mouse position.
The button must act like a windows start menu, it´s why I need it.
> The button must act like a windows start menu, it´s why I need it.

i meant if you are using a glass pane to capture the mouse clicks then the button seems to no longer being used.

ok objects, you chanleged me :)

import java.awt.Component;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

public class ToggleControl extends JFrame {
   
    MyPopup cp;
    JToggleButton tb;  
    boolean inButton = false;
   
    public ToggleControl() {
        this.addWindowListener(
            new WindowAdapter() {
                public void windowClosing( WindowEvent e ) {
                    System.exit(0);
                }
            }
        );
        this.setSize( 200, 200 );
        this.setVisible(true);
        this.setLayout( new FlowLayout() );
        cp = new MyPopup();
       
        cp.addPopupMenuListener(
                new PopupMenuListener( ) {
                              public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
                                    tb.setSelected(true);
                              }
                              public void popupMenuWillBecomeInvisible(PopupMenuEvent e ) {
                                    long time = System.currentTimeMillis() + 3000;
                                    System.out.println("popup hided " + inButton );
                                    if ( !inButton )
                                          tb.setSelected(false);
                              }
                              public void popupMenuCanceled(PopupMenuEvent arg0) {
                              }
                }
        );        
       
        tb = new JToggleButton("Start");
        this.getContentPane().add(tb);
        this.validate();
       
        tb.addMouseListener(
                    new MouseListener() {
                              public void mouseClicked(MouseEvent e) {
                                    System.out.println("mouseClicked");
                              }
                              public void mousePressed(MouseEvent e) {
                                    System.out.println("mousePressed");
                                    if( !tb.isSelected() ) {
                                          EventQueue.invokeLater(
                                                new Runnable() {  
                                                      public void run() {  
                                                    cp.show( tb, tb.getWidth(), tb.getHeight() );
                                                      }
                                                }
                                          );
                                    }
                              }
                              public void mouseReleased(MouseEvent e) {
                                    System.out.println("mouseReleased");
                              }
                              public void mouseEntered(MouseEvent e) {
                                    System.out.println("mouseEntered");
                                    inButton = true;
                              }
                              public void mouseExited(MouseEvent e) {
                                    System.out.println("mouseExited");
                                    inButton = false;
                              }
                    }
               );
    }
   
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        ToggleControl tc = new ToggleControl();
    }
   
    class MyPopup extends JPopupMenu {
       
        static final int SIDEBARWIDTH = 20;
       
        public MyPopup() {
            JMenu m = new JMenu("SubMenu");
            JMenuItem mi = new JMenuItem("SubItem 1");
            m.add(mi);
            mi = new JMenuItem("SubItem 2");
            m.add(mi);
            this.add( m );
            mi = new JMenuItem("Item 1");
            this.add( mi );
            mi = new JMenuItem("Item 2");
            this.add( mi );
        }
       
        public void show( Component c, int x, int y ) {
            super.show( c, x, y );
        }
    }

}
thanx all anyway