如何滚动两个JTextPane?

时间:2011-06-16 22:13:00

标签: java swing scroll

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

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

这是我的主要方法的代码。我已经从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);
}
});

这是一张图片,显示了我对第一个答案的实现,其中文本窗格不限于水平显示区域。 Image showing text panes that are too wide for the horizontal display area

此图像显示文本窗格在水平显示区域中受限,但此示例的原始问题是如果文本窗格很长则不垂直滚动。 Image showing text panes that are bounded horizontally

2 个答案:

答案 0 :(得分:15)

我之前使用过的技巧是使用两个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());

// ...

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

您还可以通过将滚轮事件从左侧滚动窗格重定向到右侧滚动窗格来修复鼠标滚轮滚动:

spLeft.setWheelScrollingEnabled(false);
spLeft.addMouseWheelListener(new MouseWheelListener() {
    public void mouseWheelMoved(MouseWheelEvent e) {
        spRight.dispatchEvent(e);
    }
});

答案 1 :(得分:4)

如果对JTextPane使用GridLayout,然后用JScrollPane包装,则滚动条将用于两个JTextPanes,因为GridLayout分为等长的矩形。

这样的东西应该可行(在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);

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

希望有所帮助!