<Swing Dev> [9] Crash tabbing to a checkbox with custom model (see e.g. 8074883)

Luke ldubox-coding101 at yahoo.co.uk
Sun Jun 18 22:33:15 UTC 2017


Good day,

I believe I've hit my first bug in occasional testingof the JDK-9 drops.
I hope this is an appropriate way to send feedback?

We use a customised "tri-state" checkbox, which triggers a crash when the
keyboard focus moves to it by pressing the TAB key. The issue seems related
to some focus logic changes with button-groups introduced in JDK-9.
(For example: 8074883?)

The top of the stack trace is:

java.lang.ClassCastException: 
com.example.TristateCheckBox$TristateDecorator cannot be cast to 
java.desktop/javax.swing.JToggleButton$ToggleButtonModel
     at 
java.desktop/javax.swing.LayoutFocusTraversalPolicy.accept(LayoutFocusTraversalPolicy.java:243)
     at 
java.desktop/javax.swing.SortingFocusTraversalPolicy.getComponentBefore(SortingFocusTraversalPolicy.java:435)
     at 
java.desktop/javax.swing.LayoutFocusTraversalPolicy.getComponentBefore(LayoutFocusTraversalPolicy.java:143)
     at 
java.desktop/java.awt.Component.transferFocusBackward(Component.java:8201)
     at 
java.desktop/java.awt.Component.transferFocusBackward(Component.java:8186)
     at 
java.desktop/java.awt.DefaultKeyboardFocusManager.focusPreviousComponent(DefaultKeyboardFocusManager.java:1388)
     at 
java.desktop/java.awt.DefaultKeyboardFocusManager.processKeyEvent(DefaultKeyboardFocusManager.java:1183)
     at 
java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4877)
     at 
java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2317)
     at java.desktop/java.awt.Component.dispatchEvent(Component.java:4793)
...

The relevant code in LayoutFocusTraversalPolicy.accept is:

     } else if (aComponent instanceof JComponent) {
         if (SunToolkit.isInstanceOf(aComponent,
"javax.swing.JToggleButton")) {
             JToggleButton.ToggleButtonModel model =
                     (JToggleButton.ToggleButtonModel) ((JToggleButton)
                             aComponent).getModel();   // <- Line 243
             if (model != null) {
                 ButtonGroup group = model.getGroup(); // <- Only use of 
'model'

For whatever reason (probably to do with the 3 states) the button model
is not a ToggleButtonModel, but derived from a DefaultButtonModel.

I think a simple solution is to (check? and) cast less specifically, to a
DefaultButtonModel instead. That looks to be sufficient here, and is also
what we find similar code in JToggleButton doing. For example in
JToggeleButton.getGroupSelection we see:

     if (model instanceof DefaultButtonModel) {
         ButtonGroup group = ((DefaultButtonModel) model).getGroup();
         //...

I note while JToggleButton creates a ToggleButtonModel by default, it
does not enforce it via setModel().


More background: I think we found this code (over a decade ago) from here

   http://www.javaspecialists.eu/archive/Issue082.html

(There are better solutions implementing this GUI control these days, but
I thought you might like to hear about it.)

Kind regards,
Luke Usherwood





More information about the swing-dev mailing list