runtime ClassCastException
1) I have a class MyWindow that extends JFrame
2) To MyWindow, I add a MyPanel that extends JPanel
3) MyPanel calls addMouseListener(new MyListener() ) in its constructor.
5) In the MyListener class, I have the following method:
class MyListenerextends MouseAdapter
{
publicvoid mouseEntered(MouseEvent event)
{
...
...
/**EXCEPTION**/ MyWindow window = (MyWindow) (event.getComponent().getParent() );
...
}
}
When I roll my mouse into the window, I get a ClassCastException. Why? event.getComponent() returns a Component, and the Component's getParent() method returns a Container, and this is the inheritance hierarchy of JFrame:
Object
-Component
--Container
-Window
Frame
JFrame
Why isn't the Container a MyWindow object?
[1130 byte] By [
7studa] at [2007-10-3 9:12:35]

I think the Container returned by getParent() must be the JFrame's content pane. But if I tack on successive calls to getParent(), I still can't find the JFrame. Is there an easy way to get a JPanel's enclosing JFrame?
> Why isn't the Container a MyWindow object?
Because that isn't the way that the components are layed out.
The component hierarchy (which isn't related to inheritance hierarchy) in your case looks like this:
MyPanel
javax.swing.JPanel
javax.swing.JLayeredPane
javax.swing.JRootPane
MyWindow
The "graph" shows that MyWindow isn't the parent of MyPanel.
Kaj
> I think the Container returned by getParent() must be
> the JFrame's content pane. But if I tack on
> successive calls to getParent(), I still can't find
> the JFrame. Is there an easy way to get a JPanel's
> enclosing JFrame?
Why do you need to get hold of the frame?
Ok, 4 calls to getParent() found the JFrame (I stopped at 3 before). I don't understand the JPanel in the *component* hierarchy? There's a JPanel that contains MyPanel? Why not a JFrame containing MyFrame? And, where is the content pane? After all that is what we add components to.
> Why do you need to get hold of the frame?
To dispose() it. Alternatively, I could move MyPanel and MyListener into MyFrame and declare them as private inner classes. I just started coding it as separate classes, so I was trying to use the event object to get the JFrame.
> And, where is the content pane? After all
> that is what we add components to.
Guess what. The content pane is a JPanel.
>
> > Why do you need to get hold of the frame?
>
> To dispose() it. Alternatively, I could move MyPanel
> and MyListener into MyFrame and declare them as
> private inner classes. I just started coding it as
> separate classes, so I was trying to use the event
> object to get the JFrame.
Make the frame implement an interface. Make the panel take that interface as argument, and call dispose on the interface.
Kaj
> > And, where is the content pane? After all
> > that is what we add components to.
>
> Guess what. The content pane is a JPanel.
>
Wow. I can't find anything in the whole wide world that mentions that. But I can confirm it with some code:
JFrame window = new JFrame("title");
Container cpane = window.getContentPane();
Class objType = cpane.getClass();
System.out.println(objType.getName()) //javax.swing.JPanel
For future seekers, my component hierarchy is:
MyWindow
|
JRootPane
|
JLayeredPane
|
contentPane (JPanel)
|
MyPanel
That's why it took four calls to getParent() to arrive at MyWindow:MyWindow window =
(MyWindow) event.getComponent().getParent().getParent().getParent().getParent();
>
> Make the frame implement an interface. Make the panel
> take that interface as argument, and call dispose on
> the interface.
>
> Kaj
You mean pass the frame to the panel constructor and in the panel pass the frame to the MyListener constructor? The disposing happens in mouseEntered(). What does the interface do?
> You mean pass the frame to the panel constructor and
> in the panel pass the frame to the MyListener
> constructor? The disposing happens in
> mouseEntered(). What does the interface do?
It reduces the coupling.
A better choice is atually to read about MVC. It explains how to split your code so that it becomes more modular.
Kaj