I'm having a fairly difficult problem with a sub-type super-type situation in Swing.
I have a class which extends JFrame
publicclass AvailabilitySearchFrame extends JFrame {
...
} // end class def
...and I have a sub-type of that class (intended to be run by users in a secondary office and has some of the components disabled).
publicclass RemoteAvailabilitySearchFrame extends AvailabilitySearchFrame {
...
} // end class def
Occassionally (not always...only occasionally) I get the following error message when I first create the sub-type (using
new RemoteAvailabilitySearchFrame();
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException at javax.swing.LayoutComparator.compare(Unknown Source) at java.util.Arrays.mergeSort(Unknown Source) at java.util.Arrays.sort(Unknown Source) at java.util.Collections.sort(Unknown Source) at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(Unknown Source) at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(Unknown Source) at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(Unknown Source) at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(Unknown Source) at java.awt.FocusTraversalPolicy.getInitialComponent(Unknown Source) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.SequencedEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
As you can see, it gives me virtually no information regarding what, or where, in the code is causing this. No line numbers, and none of the classes referenced in the message are mine (all Java classes). Worse still, it appears to happen randomly and at random times while execution is in progress. My first thought was to make sure I was invoking the right super-type constructor and so I went back and made sure I had my
super();
statement in place. It is, but I still get the error (once about every three or four executions).
Also I am not casting anything in either constructor. Driving me nuts...bad enough that it's happening, but I can't find any way to diagnose the problem. Any ideas? If it helps, here are the two constructors
Update--I have seen some threads here and elsewhere that indicate it may have something to do with the remove(Component comp) method, so I tried adding validate() to the end of the sub-type constructor. No luck.
I'm about out of ideas, short of changing my remove()s to setEnabled(false), maybe?
Well, if anyone is interested here's what I have...
First, I still do not know much about why it is happening or how to fix it. I did, though, come up with a workaround.
From what I read here and on some other forums, there is an unchecked (and undocumented) ClassCastException associated with remove() methods. I could not find much of an explanation or suggestions on how to prevent it, so I decided to remove the removes() and to disable the components instead.
This opened up a whole new can o' worms, though, because some of the JFrames have a lot of components. I tried disabling the Panels that contained the components, but the setEnabled(false) method did not propagate down to the children. I did some more research and discovered that this (lack of propagation) is either a bug or a feature of Swing, depending on who you ask (here's a link to a discussion thread on the Sun forum if anyone is interested -- http://forums.java.net/jive/thread.jspa?threadID=13758&start=0&tstart=0).
So, I wrote a little utility which takes a JPanel and a boolean state and recursively loops through the panel invoking setEnabled(state) on all child components. Here's the code if anyone wants it...
package net.SloanVentures.util;
import javax.swing.JPanel;
import java.awt.Component;
publicclass PanelComponentsEnabler {
publicstaticvoid enablePanelComponents(JPanel panel, boolean state) {
Component[] components = panel.getComponents();
for (int i=0; i < components.length; i++) {
Component component = (Component) components[i];
// if child component is a sub-panel, make a recursive call
if (component.getClass().toString().equals("class javax.swing.JPanel")) {
JPanel subPanel = (JPanel) component;
enablePanelComponents(subPanel, state);
} else {
component.setEnabled(state);
} // end if
} // end for
} // end enablePanelComponents
} // end class def
I set up a test loop which opened and closed the JFrame 2000 times...no ClassCastException, so I'm reasonably confident the workaround works.
However, I would still like to know why it happens and what (if anything) can be done to fix it. So, if anyone has any info, I'd love to see it.
I had the same original error (ClassCastException at javax.swing.LayoutComparator.compare etc..etc..).
The error in my program was that I had some remove(button) calls in the main thread of my java program. After I moved the removal of the buttons into the event dispatching thread (the ActionListener method processing the button pressed events and such) there were no such Exceptions any more.
It seems to me that the event dispatching mechanism gets a bit confused if components are removed in another thread at exactly the same time when an AWT event is generated.
I had this error and fixed it by running MyWindow.show() from the dispatcher thread. I think if you open more then one window at the same time from the main thread you can get threading issues (show() does not seem to be quite as thread safe as it should be!)
It happens more or less the same... but it gives me the line numbers:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException at javax.swing.LayoutComparator.compare(LayoutComparator.java:61) at java.util.Arrays.mergeSort(Arrays.java:1293) at java.util.Arrays.mergeSort(Arrays.java:1282) at java.util.Arrays.mergeSort(Arrays.java:1282) at java.util.Arrays.sort(Arrays.java:1210) at java.util.Collections.sort(Collections.java:159) at javax.swing.SortingFocusTraversalPolicy.enumerateAndSortCycle(SortingFocusTrave rsalPolicy.java:119) at javax.swing.SortingFocusTraversalPolicy.getFirstComponent(SortingFocusTraversal Policy.java:434) at javax.swing.LayoutFocusTraversalPolicy.getFirstComponent(LayoutFocusTraversalPo licy.java:148) at javax.swing.SortingFocusTraversalPolicy.getDefaultComponent(SortingFocusTravers alPolicy.java:511) at java.awt.FocusTraversalPolicy.getInitialComponent(FocusTraversalPolicy.java:152 ) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager. java:334) at java.awt.Component.dispatchEventImpl(Component.java:4282) at java.awt.Container.dispatchEventImpl(Container.java:2116) at java.awt.Window.dispatchEventImpl(Window.java:2429) at java.awt.Component.dispatchEvent(Component.java:4240) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.SequencedEvent.dispatch(SequencedEvent.java:98) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:27 3) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:17 3) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)