<Swing Dev> Possible bug - buttons do not regain rollover state after reenabling

Martin Alterisio malterisio777 at gmail.com
Tue Jan 22 16:58:51 UTC 2008


Thank you for your reply!
I kindly appreciate it.
Learned something new.

Best Regards,

Martin Alterisio

2008/1/22, Alexander Potochkin <Alexander.Potochkin at sun.com>:
>
> Hello Martin
>
> Your observation is correct,
> Swing doesn't count a button as rollovered
> if it was disabled and enabled again
> (actually I haven't seen a GUI library
> which is ready for such situations)
>
> This problem very rare affects anybody
> so I'd see it as a Swing limitation
> (however limitation is a bit too strong word for this case)
>
> While it is definitely possible to fix this bug
> I doubt it worth doing, because in this case
> we'll have to fix tons of other cases when a component
> was moved/disabled/hidden and shown again
> which is not reasonable
>
> Here is a workaround for your test case:
>
>      private void disableButtonTemporarily() {
>          button.setEnabled(false);
>          Timer timer = new Timer(1000, new ActionListener() {
>              public void actionPerformed(ActionEvent e) {
>                  button.setEnabled(true);
>                  Point l = MouseInfo.getPointerInfo().getLocation();
>                  Point buttonLocationToScreen = new Point();
>
> SwingUtilities.convertPointToScreen(buttonLocationToScreen, button);
>                  if (new Rectangle(buttonLocationToScreen,
> button.getSize()).contains(l)) {
>                      button.getModel().setRollover(true);
>                  }
>              }
>          });
>          timer.setRepeats(false);
>          timer.start();
>      }
>
>
> Thanks
> alexp
>
>
> > Hi,
> >
> > Sorry to intrude without a proper introduction. I just want some insight
> > before reporting a possible bug.
> >
> > A friend of mine asked me to help him with a problem he has with a swing
> > app. In this app some buttons are disabled for a short period of time,
> > after which, if the user has not moved the mouse, the button doesn't
> > show the rollover state after becoming enabled again. I tested this on
> > Java6 update 3, using this quick&dirty test:
> >
> > ------------
> >
> > import java.awt.event.*;
> > import javax.swing.*;
> >
> > public class RolloverTest extends JFrame {
> >     private JButton button;
> >
> >     public static void main(final String[] args) {
> >         SwingUtilities.invokeLater(new Runnable() {
> >             public void run() {
> >                 new RolloverTest();
> >             }
> >         });
> >     }
> >
> >     public RolloverTest() {
> >         super("Rollover Test");
> >         createButton();
> >         setDefaultCloseOperation(EXIT_ON_CLOSE);
> >         pack();
> >         setVisible(true);
> >     }
> >
> >     private void createButton() {
> >         button = new JButton("Press me");
> >         button.addActionListener(new ActionListener() {
> >             public void actionPerformed(ActionEvent e) {
> >                 disableButtonTemporarily();
> >             }
> >         });
> >         add(button);
> >     }
> >
> >     private void disableButtonTemporarily() {
> >         button.setEnabled(false);
> >         Timer timer = new Timer(1000, new ActionListener() {
> >             public void actionPerformed(ActionEvent e) {
> >                 button.setEnabled(true);
> >             }
> >         });
> >         timer.setRepeats(false);
> >         timer.start();
> >     }
> > }
> >
> > -----------
> >
> > Sorry I couldn't test it on the latest codebase, I don't have an
> > environment set up for that purpose. Please check if you can that this
> > also happens with later versions of Swing or the JDK.
> >
> > Also, I did some digging in the source at openjdk to see what could be
> > the problem. Since it happens not only with JButton, but also to
> > JMenuItem, JCheckBox, etc, at first I thought that the problem might be
> > in the DefaultButtonModel, that the flag was simply lost when the button
> > is disabled. But apparently DefaultButtonModel.setEnabled() unsets other
> > flags but not the rollover state, although
> > DefaultButtonModel.setRollover() prevents changes to the rollover flag
> > if the button is disabled. In consequence, I couldn't manage a
> > workaround by providing a different ButtonModel.
> >
> > It seems that AbstractButton.setEnabled() forces the rollover state to
> > change before disabling the button. There's no comment on the source as
> > to why this state change is handled by AbstractButton and not by the
> > ButtonModel, as happens with the other states. Is there a reason why
> > AbstractButton.setEnabled() has to handle the rollover and not
> > ButtonModel.setEnabled()? It seems that this is due to the order of how
> > event propagation is to occur, but I'm uncertain.
> >
> > ----------
> >
> > setEnabled in AbstractButton:
> >
> >     public void setEnabled(boolean b) {
> >         if (!b && model.isRollover()) {
> >             model.setRollover(false);
> >         }
> >         super.setEnabled(b);
> >         model.setEnabled(b);
> >     }
> >
> > setEnabled in DefaultButtonModel:
> >
> >     public void setEnabled(boolean b) {
> >         if(isEnabled() == b) {
> >             return;
> >         }
> >
> >         if (b) {
> >             stateMask |= ENABLED;
> >         } else {
> >             stateMask &= ~ENABLED;
> >             // unarm and unpress, just in case
> >             stateMask &= ~ARMED;
> >             stateMask &= ~PRESSED;
> >         }
> >
> >
> >         fireStateChanged();
> >     }
> >
> > ----------
> >
> > If AbstractButton didn't force the rollover to false, and let the
> > ModelButton handle this, an implementation of ModelButton could store
> > the right state of the rollover even though it would be superseded by
> > the enabled state ( i.e. although rollover is true, it would be shown as
> > false if enabled is false). Therefore, when the button is reenabled, the
> > rollover could be restored as expected. But that's only if there isn't a
> > special reason why AbstractButton has to handle the rollover state
> > before disabling the button.
> >
> > That's all. Sorry for the long mail.
> >
> > Best Regards,
> >
> > Martin Alterisio
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20080122/1566abf7/attachment.html>


More information about the swing-dev mailing list