<Swing Dev> Possible bug - buttons do not regain rollover state after reenabling
Martin Alterisio
malterisio777 at gmail.com
Tue Jan 22 16:07:44 UTC 2008
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/3782044a/attachment.html>
More information about the swing-dev
mailing list