2011-06-16 69 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