2011-02-27 107 views
2

我有一個包含垂直框的JScrollPane。我在Box的頂部插入新的JPanel。如果我使用滾動條向下滾動,我希望當前視圖保持在我向下滾動的位置。例如,如果我在框中有50個面板並使用滾動條來查看面板20,我希望視圖保留在方框20上,即使其他方框添加在頂部。此外,如果我使用滾動條向上滾動到頂部,我希望視圖在添加新面板時顯示新面板。任何想法如何做到這一點?JScrollPane在頂部添加JPanel並保持當前滾動視圖

順便說一句,沒有必要使用JScrollPane或Box。示例代碼只是爲了幫助解釋我想要做的事情。

示例代碼:

 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class TestScrollPane extends JFrame { 

    JScrollPane scrollPane; 
    Box box; 
    private static int panelCount = 0; 

    public TestScrollPane() { 
     setPreferredSize(new Dimension(200, 400)); 
     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 

     scrollPane = new JScrollPane(); 
     scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
     scrollPane.getVerticalScrollBar().setUnitIncrement(15); 
     box = Box.createVerticalBox(); 
     scrollPane.getViewport().add(box); 

     this.add(scrollPane); 
     this.pack(); 
     this.setLocationRelativeTo(null); 
     this.setVisible(true); 

     Timer t = new Timer(500, new ActionListener() { 

      public void actionPerformed(ActionEvent ae) { 
       box.add(new TestPanel(), 0); 
       scrollPane.validate(); 
      } 
     }); 
     t.setRepeats(true); 
     t.start(); 
    } 

    public class TestPanel extends JPanel { 

     int myId = panelCount++; 

     public TestPanel() { 
      this.setLayout(new GridBagLayout()); 
      this.setBorder(BorderFactory.createBevelBorder(1)); 
      JLabel label = new JLabel("" + myId); 
      label.setHorizontalAlignment(JLabel.CENTER); 
      label.setVerticalAlignment(JLabel.CENTER); 

      this.setMaximumSize(new Dimension(100, 100)); 
      this.setPreferredSize(new Dimension(100, 100)); 

      this.add(label); 
     } 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       TestScrollPane testScrollPane = new TestScrollPane(); 
      } 
     }); 
    } 
} 

編輯: 這是我最終改變的代碼。我沒有看到明顯的情況,感覺有些愚蠢。不管怎樣,對那些幫助過的人來說。

 
      public void actionPerformed(ActionEvent ae) { 
       Point view = scrollPane.getViewport().getViewPosition(); 
       TestPanel panel = new TestPanel(); 
       box.add(panel, 0); 
       scrollPane.validate(); 
       if (view.y != 0) { 
        view.y += panel.getHeight(); 
        scrollPane.getViewport().setViewPosition(view); 
       } 
      } 

順便說一句,我有交叉張貼了這個問題http://www.coderanch.com/t/528829/GUI/java/JScrollPane-adding-JPanels-at-top#2398276僅供參考對於那些可能關心。

+0

我給你,你用它來解決你的問題的代碼的想法和你邀功的解決方案。祝你下次有問題時,祝你好運。 – camickr 2011-02-28 05:07:39

+0

@camickr您是否想要讚揚JB Nizet的解決方案?無論如何,在我已經根據JB的想法編寫代碼之前,我還沒有讀過你的帖子。我想你在晚會上晚了幾個小時。讀下來。 Thanx反正,但。 – coreshift 2011-03-01 19:37:17

+0

我的解決方案在您編輯的解決方案前三個小時發佈。我還沒有看到其他人發佈的解決方案。 – camickr 2011-03-02 04:13:56

回答

0

您可以獲取想要顯示的組件的邊界(使用JComponent的getBounds方法),並將其用作JViewPort的scrollRectToVisible方法的輸入。

+0

這是一種可能性,但會導致視圖跳轉到面板。我寧願如果視圖保持完全按照用戶在向下滾動時看到的那樣。 – coreshift 2011-02-27 11:27:48

+0

然後,您可以在添加面板之前在視口上調用getViewRect(),通過添加新添加的面板的高度將獲取的矩形轉換爲底部,然後在面板添加之前將scrollRectToVisible返回到視口的位置。 – 2011-02-27 12:12:55

+0

是的,簡單,事後迴應顯而易見。 Thanx,非常感謝。 – coreshift 2011-02-27 19:13:08

0

喜歡的東西:

Timer t = new Timer(1000, new ActionListener() { 

     public void actionPerformed(ActionEvent ae) { 
      TestPanel panel = new TestPanel(); 
      box.add(panel, 0); 
      JViewport vp = scrollPane.getViewport(); 
      Point p = vp.getViewPosition(); 
      p.y += panel.getPreferredSize().height; 
      scrollPane.revalidate(); 
      vp.setViewPosition(p); 
     } 
    }); 
相關問題