Swing: How could I get JInternalFrame treated equally to other components inside a container?
-
20-08-2019 - |
Question
Background information:
I am implementing a visual diagram editor, which consists of
- different complex elements (re-sizable, with title bar, sub-elements) and
- different simple elements (not re-sizable, no title bar, no sub-elements).
All elements are draggable.
I am using JInternalFrame (for complex elements) along with JPanel (for simple elements) to represent elements of a schematic diagram. There is a container (either a JDesktopPane or a JLayeredPane), which contain all these elements.
I have several problems with this concept:
Case 1 - The container is a JDesktopPane:
- JInternalFrames are always above other elements.
- Clicking other elements don't "deactivate" previously active JInternalFrame
Case 2 - The container is a JLayeredPane:
- After clicking some elements inside a JInternalFrame, it stays "activated" forever.
Case 3 - JInternalFrame used for everything, but without decoration for simple elements:
- My custom border (which is needed when I manually remove JInternalFrame's title bar) is every time replaced by current LAF border, after activating/deactivating the JInternalFrame.
I don't get the whole concepts behind activating JInternalFrames anyway. If I could make a JInternalFrame not activable at all, I could choose Case 2 any would be happy.
Please advice me, what would be an simple and straightforward solution to given problems.
NOTE: Selection of components and activation of JInternalFrame seem to be different things.
Solution
I might misunderstand your problem. Have you tried to look at the setSelected() method of JIF? It seems there are support for method override and vetoable activation events.
Edit: Maybe we have some terminological misunderstanding as the javadoc states:
/**
* Selects or deselects the internal frame
* if it's showing.
* A <code>JInternalFrame</code> normally draws its title bar
* differently if it is
* the selected frame, which indicates to the user that this
* internal frame has the focus.
* When this method changes the state of the internal frame
* from deselected to selected, it fires an
* <code>InternalFrameEvent.INTERNAL_FRAME_ACTIVATED</code> event.
* If the change is from selected to deselected,
* an <code>InternalFrameEvent.INTERNAL_FRAME_DEACTIVATED</code> event
* is fired.
*
* @param selected a boolean, where <code>true</code> means this internal frame
* should become selected (currently active)
* and <code>false</code> means it should become deselected
* @exception PropertyVetoException when the attempt to set the
* property is vetoed by the <code>JInternalFrame</code>
*
* @see #isShowing
* @see InternalFrameEvent#INTERNAL_FRAME_ACTIVATED
* @see InternalFrameEvent#INTERNAL_FRAME_DEACTIVATED
*
* @beaninfo
* constrained: true
* bound: true
* description: Indicates whether this internal frame is currently
* the active frame.
*/
Edit 2: Now I re-read your 2nd case. I would say each JIF has its own separated focus/selection environment. You could create a method which traverses all your JIFs and deselects anything in it unless its the component you wanted to be selected.
OTHER TIPS
give this a try when you initialize your JInternalFrame=
new JInternalFrame(<your args>) {
protected void fireInternalFrameEvent(int id){
if (id != InternalFrameEvent.INTERNAL_FRAME_ACTIVATED) {
super.fireInternalFrameEvent(id);
}
}
};
note that looking at the code in JInternalFrame.setSelected(boolean)
, setSelected and 'actvation' are tied together in process, in that setSelected fires not only property changes for Selection, but also calls fireInternalFrameEvent(InternalFrameEvent.INTERNAL_FRAME_ACTIVATED)
as well.