Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scroll two JTextPane's?

Tags:

java

scroll

swing

I am a Swing novice using NetBeans. I want to vertically scroll two side-by-side JTextPane's. The scrolling should be syncronized and done through a single scrollbar.

If I add JTextPanes from the NetBean designer they are automatically put inside a JScrollPane so they scroll independently. I have deleted the enclosing scroll panes and put them in a JPanel instead so the JPanel can be the client of a single JScrollPane. This seems to work except that when the JTextPanes are very long they seem to go beyong the end of the JPanel. I can scroll the panel and both text panes to a certain point. When I reach the bottom I can put a cusor in one of the text panes and arrow down beyond my field of view.

Here is code from my main method. I have copied the layout from something that was generated by the NetBeans designer.

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
topFrame aTopFrame = new topFrame();
JScrollPane scollBothDiffs = new javax.swing.JScrollPane();
JPanel bothDiffsPanel = new javax.swing.JPanel();
JTextPane leftDiffPane = diffPane1;
JTextPane rightDiffPane = diffPane2;


javax.swing.GroupLayout bothDiffsPanelLayout = new javax.swing.GroupLayout(bothDiffsPanel);
bothDiffsPanel.setLayout(bothDiffsPanelLayout);
bothDiffsPanelLayout.setHorizontalGroup(
    bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(bothDiffsPanelLayout.createSequentialGroup()
        .addGap(20, 20, 20)
        .addComponent(leftDiffPane, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(rightDiffPane, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addContainerGap(52, Short.MAX_VALUE))
);
bothDiffsPanelLayout.setVerticalGroup(
    bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, bothDiffsPanelLayout.createSequentialGroup()
        .addContainerGap()
        .addGroup(bothDiffsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
            .addComponent(rightDiffPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 630, Short.MAX_VALUE)
            .addComponent(leftDiffPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 630, Short.MAX_VALUE))
        .addContainerGap())
);

scollBothDiffs.setViewportView(bothDiffsPanel);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(aTopFrame.getContentPane());
aTopFrame.getContentPane().setLayout(layout);
layout.setHorizontalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
        .addGap(20, 20, 20)
        .addComponent(scollBothDiffs, javax.swing.GroupLayout.DEFAULT_SIZE, 997, Short.MAX_VALUE)
        .addContainerGap())
);
layout.setVerticalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(scollBothDiffs, javax.swing.GroupLayout.DEFAULT_SIZE, 671, Short.MAX_VALUE)
        .addContainerGap())
);

aTopFrame.pack();
aTopFrame.setVisible(true);
}
});

Here is an image that shows my implementation of the first answer where the text panes are not limited to the horizontal display area. Image showing text panes that are too wide for the horizontal display area

And this image shows the text panes limited in the horizontal display area but this example has the original issue of not scrolling vertically if the text panes are very long. Image showing text panes that are bounded horizontally

like image 869
mikeatv Avatar asked Jun 16 '11 22:06

mikeatv


People also ask

How do I insert a scroll bar on my jtextpane?

27.6k 47 128 189 To insert a scroll bar on your new JTextPane, just use a JScrollPane: JTextPane txt = new JTextPane (); JScrollPane jsp = new JScrollPane (txt);

How to scroll text and images at the same time using jQuery?

For example, you could have text in one and images in the other and want to scroll both at the same time. To achieve this, we will do it with the jQuery JavaScript library. And no.... jQuery is not dead. To synchronize the scroll positions we can use .scrollTop () to know the position of the content with respect to the top of the page.

How to scroll two divs at the same time using jQuery?

In case you have two divs of different sizes you may sometimes want to scroll both at the same time but at different speeds depending on their size. For example, you could have text in one and images in the other and want to scroll both at the same time. To achieve this, we will do it with the jQuery JavaScript library.

How to synchronize scroll positions in jQuery?

And no.... jQuery is not dead. To synchronize the scroll positions we can use .scrollTop () to know the position of the content with respect to the top of the page. First, we place the page div with the main content and then the block div with the secondary content that will scroll with respect to the main one according to its position.


2 Answers

A trick I've used before is to use two JScrollPanes, hide the vertical scroll bar for the left pane, and set its model to the model for the right scroll pane. That way, when the user scrolls the right scroll bar, it updates both scroll panes, since they share the same model. Here is an example that also has dual synchronized horizontal scroll bars at the bottom:

JTextPane leftDiffPane = diffPane1;
JTextPane rightDiffPane = diffPane2;
JScrollPane spLeft = new JScrollPane(leftDiffPane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
JScrollPane spRight = new JScrollPane(leftDiffPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
spLeft.getHorizontalScrollBar().setModel(spRight.getHorizontalScrollBar().getModel());
spLeft.getVerticalScrollBar().setModel(spRight.getVerticalScrollBar().getModel());

// ...

Note that it might not work so well if your JTextPanes have different sizes (I haven't tried it, but my best guess is it would cause problems)

You can also fix mouse wheel scrolling by redirecting wheel events from the left scroll pane to the right one:

spLeft.setWheelScrollingEnabled(false);
spLeft.addMouseWheelListener(new MouseWheelListener() {
    public void mouseWheelMoved(MouseWheelEvent e) {
        spRight.dispatchEvent(e);
    }
});
like image 182
Kevin K Avatar answered Sep 30 '22 14:09

Kevin K


If you use a GridLayout for both of your JTextPane and then wrap it with JScrollPane, the Scroll Bar will be for both JTextPanes since the GridLayout gets divided into equal sized rectangles.

Something like this should work (Tested on Java 6)

// Text Panes initialization. I am just setting text so you can see
// what each pane is.
JTextPane leftDiffPane = new JTextPane();
leftDiffPane.setText("left");
JTextPane rightDiffPane = new JTextPane();
rightDiffPane.setText("right");

// Wrap the Text Panes with a Panel since you can only
// have a single component within a scroll pane.      
JPanel bothDiffsPanel = new JPanel();
bothDiffsPanel.setLayout(new GridLayout(1, 2));
bothDiffsPanel.add(leftDiffPane, BorderLayout.WEST);
bothDiffsPanel.add(rightDiffPane, BorderLayout.EAST);

// Fill in the frame with both of the panels.
setLayout(new BorderLayout());
add(new JScrollPane(bothDiffsPanel), BorderLayout.CENTER);

If you use the above approach, if amending text to either JTextPanes overflow the dimensions, the scroll bar will appear and when used, it will scroll both of the components. If amending text overflows a component, it will scroll down so your input will be visible.

Hope that helps!

like image 44
Mohamed Mansour Avatar answered Sep 30 '22 14:09

Mohamed Mansour