Skip to main content

MouseEvents: JTree in JScrollPane with Layer

4 replies [Last post]
cedarsoft
Offline
Joined: 2008-09-13

Hi,

I have a very special requirement I think JXLayer is a great solution
for.

I have a JTree within a scroll pane. Now the customer wants me to show
some special information at the top of visible rectangle of the tree.
But only sometimes (depending on the state/scroll position of the tree).

I implemented that and it works great (thanks for your work!).

Now the problem:
Mouse clicks on that information area must not result in
expanding/collapsing/selecting the elements of the underlying tree.

I tried to overwrite
org.jdesktop.jxlayer.plaf.AbstractLayerUI#processMouseEvent. But the
expansion happens *before* that method is called. This happens within
the TreeUI classes...

So what way do you suggest to catch some mouse events using a layer?

This is the code I use to create the layer:

<br />
JScrollPane scrollPane = new JScrollPane( getTree());<br />
JXLayer layer = new JXLayer( scrollPane );<br />
layer.setUI( new MyLayerUI);<br />

The layer is then added to the content pane.

(Yes, this is a repost from the user mailing list. Since there weren't any messages I hope that this forum is the better communication channel).

Thanks,

Johannes Schneider

I have created a small test case that shows the problem (notice the order of the messages on System.out):

<br />
package org.jdesktop.jxlayer.demo;</p>
<p>import org.jdesktop.jxlayer.JXLayer;<br />
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;</p>
<p>import javax.swing.JFrame;<br />
import javax.swing.JScrollPane;<br />
import javax.swing.JTree;<br />
import javax.swing.SwingUtilities;<br />
import javax.swing.event.TreeModelListener;<br />
import javax.swing.tree.TreeModel;<br />
import javax.swing.tree.TreePath;<br />
import java.awt.event.MouseEvent;</p>
<p>public class TreeExpandDemo extends JFrame {<br />
public TreeExpandDemo() {<br />
super( "JXLayer MouseScrollableDemo" );<br />
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );</p>
<p>JScrollPane jScrollPane = createTreeScrollPane();</p>
<p>JXLayer layer = new JXLayer( jScrollPane,<br />
new AbstractLayerUI() {<br />
// {<br />
// setLayerEventMask( AWTEvent.MOUSE_EVENT_MASK );<br />
// }<br />
//<br />
// protected boolean isAWTEventListenerEnabled() {<br />
// return true;<br />
// }</p>
<p>@Override<br />
protected void processMouseEvent( MouseEvent e,<br />
JXLayer l ) {<br />
super.processMouseEvent( e, l );<br />
if ( e.getID() == MouseEvent.MOUSE_CLICKED ) {<br />
System.out.println( "Layer.processMouseEvent" );<br />
}<br />
}<br />
} );</p>
<p>add( layer );<br />
setSize( 800, 600 );<br />
setLocationRelativeTo( null );<br />
}</p>
<p>private JScrollPane createTreeScrollPane() {<br />
JTree tree = new JTree( new TreeModel() {<br />
public Object getRoot() {<br />
return "theRoot";<br />
}</p>
<p>public Object getChild( Object parent, int index ) {<br />
return index;<br />
}</p>
<p>public int getChildCount( Object parent ) {<br />
return 20;<br />
}</p>
<p>public boolean isLeaf( Object node ) {<br />
return false;<br />
}</p>
<p>public void valueForPathChanged( TreePath path, Object newValue )<br />
{<br />
throw new UnsupportedOperationException();<br />
}</p>
<p>public int getIndexOfChild( Object parent, Object child ) {<br />
return ( Integer ) child;<br />
}</p>
<p>public void addTreeModelListener( TreeModelListener l ) {<br />
}</p>
<p>public void removeTreeModelListener( TreeModelListener l ) {<br />
}<br />
} ) {<br />
@Override<br />
protected void setExpandedState( TreePath path, boolean state ) {<br />
System.out.println( "TreeExpandDemo.setExpandedState" );<br />
super.setExpandedState( path, state );<br />
}<br />
};<br />
return new JScrollPane( tree );<br />
}</p>
<p>public static void main( String[] args ) throws Exception {<br />
SwingUtilities.invokeLater( new Runnable() {<br />
public void run() {<br />
new TreeExpandDemo().setVisible( true );<br />
}<br />
} );<br />
}<br />
}<br />

Message was edited by: cedarsoft

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
pietblok
Offline
Joined: 2003-07-17

Hi Johannes,

As I found your question very interesting, I also did some tests.

I found that JTree does not expand/collapse on MOUSE_CLICKED, but on MOUSE_PRESSED.

So, if you change your TreeExpandDemo into testing on pressed rather than testing on clicked, you will see that the events are processed in the order: layer first, tree second.

In your real case I think that you will have to investigate all MouseEvents and determine if you want to cunsume them.

Hope this is some additional help,

Piet

cedarsoft
Offline
Joined: 2008-09-13

Aaaaah, thanks. I am so stupid.....
Of course. Well I think I was a little tired yesterday.

Thanks for finding that out. JXLayer works as expected...

alexfromsun
Offline
Joined: 2005-09-05

Hello Johannes

This forum is the best place for this kind of questions, indeed

If you want a mouseEvent to be consumed, just call mouseEvent.consume();
and it won't be passed to the underlying component,
the following code blocks all mouseEvents (but not mouseMotion and mouseWheel ones)

[code]
protected void processMouseEvent(MouseEvent e,
JXLayer l) {
super.processMouseEvent(e, l);
e.consume();
}
[/code]

I suggest consuming the event depending on its coordinates

Please keep me informed about the new features JXLayer is good for

Thanks
alexp

alexfromsun
Offline
Joined: 2005-09-05

By the way there is another useful technique:

you can implement that special text as the non-opaque component
and place it to the layer's glassPane. If you enable mouseEvents for this component
or just add a mouseListener to it, it will also consume the mouseEvents

In the MouseScrollableUI, the scrolling indicator is implemented as the separate component

Thanks
alexp