Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Control two JScrollPanes with one JScrollBar

615 views
Skip to first unread message

surferDave

unread,
Apr 16, 2003, 11:49:03 AM4/16/03
to
In my application, I have two JScrollPanes side by side. The left
hand scroll pane contains a JTree, the right hand scroll pane contains
a jtable, where each row in the table contains information relating
its adjacent node in the tree.

Both scroll panes are the same size.

What i want to do, is to hide the scrollbar for the left hand scroll
pane - and control the scrolling for both scrollpanes by using the
right hand scroll bar.

I have searched through this newsgroups and tried the following
approaches:


A) Using an AdjustmentListener

scrollPane1.setVerticalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

scrollPane2.getVerticalScrollBar().addAdjustmentListener(new
AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
scrollPane1.getVerticalScrollBar().setValue(e.getValue());
}
});


The problem with this is that it does work - but is slow and the
scrolling of the first scroll bar is always delayed.

B) Setting the model

I found this suggestion in a newsgroup:

JScrollPane first = ...; // table scrollPane
JScrollPane second = ...; // tree scrollPane

first.getVerticalScrollBar()
.setModel(second.getVerticalScrollBar().getModel());


The problem with this is that while the 2 scroll bars are prefectly in
sync - only the tree scroll pane actually scrolls.


The ideal solution would be one where one vertical scroll bar could
control two models. Has anyone had a similar problem to solve - this
has been puzzling me at work for a couple of days now.


Also, there is a chance that the scroll panes may end up different
sizes - would this have a big effect on any possible solution chosen?


Thanks in advance

JuddMan!

unread,
Apr 16, 2003, 11:22:56 PM4/16/03
to

"surferDave" <dafydd_d...@yahoo.co.uk> wrote in message
news:46ad4ad2.03041...@posting.google.com...

> In my application, I have two JScrollPanes side by side. The left
> hand scroll pane contains a JTree, the right hand scroll pane contains
> a jtable, where each row in the table contains information relating
> its adjacent node in the tree.
>
> Both scroll panes are the same size.
>
> What i want to do, is to hide the scrollbar for the left hand scroll
> pane - and control the scrolling for both scrollpanes by using the
> right hand scroll bar.
>

why not just put the tree and list side-by-side (using something like
BoxLayout) and then put them both into the one ScrollPane?


SPC

unread,
Apr 17, 2003, 10:22:03 AM4/17/03
to
It sounds like you have a requirement for a TreeTable. It combines a
tree and a table into a single unit. Really quite neat, and a good
demonstration of just what y0ou can do with Swing if you've a mind to.
I'd like to see some of the native code wrapper toolkits come up with
something similar :-)

Try this link:
http://java.sun.com/products/jfc/tsc/articles/treetable2/index.html

R. Kevin Cole

unread,
Apr 17, 2003, 1:33:26 PM4/17/03
to
The trick is to synchronize the JScrollBar data models. This example
should be adaptable to JSliders and JProgressBars.

Try this:
--------------------------------- cut here ------------------------------------

import java.awt.*;
import java.util.*;

import javax.swing.*;
import javax.swing.event.*;


/**
* Simple panel that illustrates the synchronization of two JScrollPanes.
* The number of elements in the two JList components do not have to be
* the same. The ChangeListener will synchronize their respective
* BoundedRangeModels and scale as necessary.
* <p> Note: Since it is the right JScrollBar's model-ChangeListener that listens
* for changes from the left JScrollBar, it is the right JList that controls
* the total number of elements shown in the JScrollPanes. </p>
*
* @author R. Kevin Cole
*/
public class ScrollBarSynchronizer extends JPanel
{
/**
* Two JLists are created and initialized from Vectors and
* then added to JScrollPanes to test the synchronized JScrollBars.
*/
public ScrollBarSynchronizer()
{
super( new BorderLayout() );

// create something to scroll
Vector leftData = new Vector();
Vector rightData = new Vector();
for( int i = 0; i < 71; i++ )
{
rightData.add( "Right " + i );

// the modulo operator is used to create a different number
// of elements within each scrolling region.
if( (i % 2) == 0 )
leftData.add( "Left " + i );
}
JScrollPane leftScrollPane = new JScrollPane( new JList( leftData ) );
leftScrollPane.setVerticalScrollBarPolicy( JScrollPane.VERTICAL_SCROLLBAR_NEVER );

JScrollPane rightScrollPane = new JScrollPane( new JList( rightData ) );

JScrollBar leftBar = leftScrollPane.getVerticalScrollBar();
JScrollBar rightBar = rightScrollPane.getVerticalScrollBar();

MyChangeListener listener = new MyChangeListener(leftBar.getModel());
rightBar.getModel().addChangeListener( listener );

JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT
, leftScrollPane
, rightScrollPane );
add( split, BorderLayout.CENTER );
}

/**
* Test routine.
*/
public static void main( String[] arg )
{
JFrame frame = new JFrame("Test ScrollBarSynchronizer");
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

frame.setContentPane( new ScrollBarSynchronizer() );
frame.setSize( 640, 480 );
frame.setLocation( 100, 100 );
frame.setVisible(true);
}
}

/**
* Synchronize the data models of any two JComponents that use a
* BoundedRangeModel ( such as a JScrollBar, JSlider or ProgressBar).
*
* @see javax.swing.BoundedRangeModel
* @see javax.swing.event.ChangeListener
* @Author R. Kevin Cole
*/
class MyChangeListener implements ChangeListener
{
private BoundedRangeModel myModel;

/**
* @param model This model is forced to move in synchronization
* to this ChangeListener's event-source.
*/
public MyChangeListener( BoundedRangeModel model )
{
myModel = model;
}


// - begin - implementation of ChangeListener
//
/**
* Envoked when the target of the listener has changed its state.
*/
public void stateChanged( ChangeEvent e )
{
BoundedRangeModel sourceModel = (BoundedRangeModel) e.getSource();

int sourceDiff = sourceModel.getMaximum() - sourceModel.getMinimum();
int destDiff = myModel.getMaximum() - myModel.getMinimum();
int destValue = sourceModel.getValue();

if( sourceDiff != destDiff )
destValue = (destDiff * sourceModel.getValue())/sourceDiff;

myModel.setValue( myModel.getMinimum() + destValue );
}
//
// - end - implementation of ChangeListener

}

--------------------------------- cut here ------------------------------------

0 new messages