2011-06-16 100 views
8

我是一名使用NetBeans的Swing新手。我想垂直滚动两个并排的JTextPane。滚动应该同步并通过单个滚动条完成。如何滚动两个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

回答

14

我之前使用的一个技巧是使用两个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); 
    } 
}); 
+0

这几乎可以工作,但左侧窗格比右侧宽,因为右侧有一些宽度被滚动条所吞噬。这意味着两个窗格不会相同,因此当您沿着窗格向下时文本不同步。 – mikeatv 2011-06-16 23:58:21

+0

@mikeatv:阅读正确使用布局管理器的Swing教程,确保两个JScrollPanes都显示相同的滚动条。 – 2011-06-17 00:56:38

+2

+1,无需隐藏滚动条,只需共享模型即可使用滚动条滚动两个文本窗格。是的,这种技术只适用于相同尺寸的文本窗格。 – camickr 2011-06-17 01:38:50

4

如果使用GridLayout为您的JTextPane,然后用JScrollPane包起来,滚动条将是自GridLayout都JTextPanes被分成相等大小的矩形。

像这样的东西应该工作(测试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溢出的尺寸,会出现滚动条,在使用时,它会滚动这两个组件。如果修改文本会溢出组件,它将向下滚动,以便您的输入可见。

希望有帮助!

+0

这看起来很有希望。谢谢。但是现在文本窗格不受水平显示区域的限制。他们不包装和滚动的方式旁边。包装是在第一种情况下使文本窗格如此之长的原因。为了进行比较,需要同时显示窗格。 – mikeatv 2011-06-16 23:42:50

+0

没问题,你的意思是受限于水平显示区域?上面的窗格在同一时间可见,用于比较。如果左侧添加20行,右侧添加20行,但查看区域只有10行,如果您滚动左侧窗格,则右侧窗格将滚动。你想要不同的行为吗? – 2011-06-17 00:42:33

+0

我已将图像添加到问题中,以显示我的意思是不受水平显示区域限制的文本窗格。我希望他们分割封闭框架的水平显示区域。 – mikeatv 2011-06-17 02:43:47