2011-02-27 6 views
2

세로 상자가있는 JScrollPane이 있습니다. 상자 상단에 새로운 JPanel을 삽입하고 있습니다. 스크롤 막대를 사용하여 아래로 스크롤하면 현재보기가 아래로 스크롤 된 곳으로 유지됩니다. 예를 들어, 상자에 50 개의 패널이 있고 패널 20을보기 위해 스크롤 막대를 사용하는 경우 다른 상자를 맨 위에 추가하더라도보기가 상자 20에 남아있게하고 싶습니다. 또한 스크롤 막대를 사용하여 맨 위로 위로 스크롤하면 뷰를 추가 할 때 새 패널을 표시하고 싶습니다. 어떤 생각을 어떻게 할 것인가?JScrollPane 상단에 JPanels를 추가하고 현재 스크롤보기를 유지

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

BTW, 난 간 상관 수있는 것들에 대해 그냥 참고로 http://www.coderanch.com/t/528829/GUI/java/JScrollPane-adding-JPanels-at-top#2398276이 질문을 게시했다.

+0

나는 당신이 문제를 해결하기 위해 사용하는 코드에 대한 아이디어를 제공하고 솔루션에 대한 크레딧을 가지고. 다음에 질문 할 때 도움을 얻으십시오. – camickr

+0

@camickr JB Nizet의 솔루션에 대한 크레딧을 얻으려고하십니까? 어쨌든, 나는 이미 JB의 아이디어에 기초한 코드를 작성할 때까지 귀하의 게시물을 읽지 않았습니다. 몇 시간 늦어서 파티에 늦은 것 같아요. 아래를 읽으십시오. 고맙습니다. – coreshift

+0

내 솔루션이 편집 된 솔루션보다 3 시간 전에 게시되었습니다. 나는 다른 누군가가 올린 해결책을 아직 보지 못했다. – camickr

답변

0

JComponent의 getBounds 메소드를 사용하여 표시하려는 구성 요소의 경계를 가져 와서 JViewPort의 scrollRectToVisible 메소드에 대한 입력으로 사용할 수 있습니다. 같은

+0

그럴 수도 있지만 뷰가 패널로 점프하게됩니다. 사용자가 아래로 스크롤 할 때 보았던 것처럼보기가 그대로 남아 있으면 더 좋을 것입니다. – coreshift

+0

그런 다음 패널을 추가하기 전에 뷰포트에서 getViewRect()를 호출하고 새로 추가 한 패널의 높이를 더하여 얻은 사각형을 맨 아래로 변환 한 다음 scrollRectToVisible을 사용하여 패널 추가 전에 뷰포트가 있던 위치로 돌아갈 수 있습니다. –

+0

네, 간단하고 뒤늦은 답변이 분명했습니다. 고맙습니다, 많이 고맙습니다. – coreshift

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