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


Reply via email to