如何滚动两个JTextPane?

时间:2021-09-23 10:54:36

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.

我是使用NetBeans的Swing新手。我想垂直滚动两个并排的JTextPane。滚动应该同步并通过单个滚动条完成。

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.

如果我从NetBean设计器添加JTextPanes,它们会自动放入JScrollPane中,以便它们独立滚动。我删除了封闭的滚动窗格并将它们放在JPanel中,因此JPanel可以是单个JScrollPane的客户端。这似乎有效,除了当JTextPanes非常长时,它们似乎在JPanel的末尾。我可以将面板和两个文本窗格滚动到某个点。当我到达底部时,我可以在其中一个文本窗格中放置一个cusor,并将箭头放在我的视野之外。

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

这是我的主要方法的代码。我已经从NetBeans设计器生成的内容中复制了布局。

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. 如何滚动两个JTextPane?

这是一个图像,显示我对第一个答案的实现,其中文本窗格不限于水平显示区域。

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. 如何滚动两个JTextPane?

此图像显示在水平显示区域中限制的文本窗格,但是如果文本窗格很长,则此示例具有不垂直滚动的原始问题。

2 个解决方案

#1


14  

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:

我以前使用过的技巧是使用两个JScrollPanes,隐藏左窗格的垂直滚动条,并将其模型设置为右侧滚动窗格的模型。这样,当用户滚动右滚动条时,它会更新两个滚动窗格,因为它们共享相同的模型。这是一个在底部也有双重同步水平滚动条的示例:

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)

请注意,如果您的JTextPanes具有不同的大小,它可能无法正常工作(我没有尝试过,但我最好的猜测是它会导致问题)

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);
    }
});

#2


4  

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.

如果对两个JTextPane使用GridLayout然后用JScrollPane包装它,则Scroll Bar将用于两个JTextPanes,因为GridLayout被分成相等大小的矩形。

Something like this should work (Tested on Java 6)

这样的东西应该工作(在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.

如果使用上述方法,如果将文本修改为JTextPanes溢出维度,则会出现滚动条,使用时,它将滚动两个组件。如果修改文本溢出组件,它将向下滚动,以便您的输入可见。

Hope that helps!

希望有所帮助!

#1


14  

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:

我以前使用过的技巧是使用两个JScrollPanes,隐藏左窗格的垂直滚动条,并将其模型设置为右侧滚动窗格的模型。这样,当用户滚动右滚动条时,它会更新两个滚动窗格,因为它们共享相同的模型。这是一个在底部也有双重同步水平滚动条的示例:

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)

请注意,如果您的JTextPanes具有不同的大小,它可能无法正常工作(我没有尝试过,但我最好的猜测是它会导致问题)

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);
    }
});

#2


4  

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.

如果对两个JTextPane使用GridLayout然后用JScrollPane包装它,则Scroll Bar将用于两个JTextPanes,因为GridLayout被分成相等大小的矩形。

Something like this should work (Tested on Java 6)

这样的东西应该工作(在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.

如果使用上述方法,如果将文本修改为JTextPanes溢出维度,则会出现滚动条,使用时,它将滚动两个组件。如果修改文本溢出组件,它将向下滚动,以便您的输入可见。

Hope that helps!

希望有所帮助!