2012-02-07 29 views
7

Tôi có một số JPanel (màu vàng) được đặt trong JScrollPane.Tại sao JPanel của tôi nằm trong JScrollPane không di chuyển?

pic1

Khi tôi nhập một số văn bản trong JTextPane, nó thay đổi kích thước, nhưng thanh cuộn dọc vẫn không hoạt động. yelowPanel.getSize() trả về cùng giá trị trước đó.` (Bạn có thể thấy nó trên redPanel).

pic2

Vì vậy, làm thế nào tôi có thể làm mới yellowPanel? Tôi muốn cuộn bảng theo chiều dọc. Tôi cố gắng để:

panelCreating.revalidate(); 
panelCreating.invalidate(); 
panelCreating.repaint(); 

chỉ việc panelCreating.setPreferredSize(new Dimension(333, 777)); nhưng tôi không biết những gì kích thước để thiết lập. Nó phụ thuộc vào nội dung.

Có một ví dụ nhỏ:

package swingtest; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextPane; 

public class SwingTest extends JFrame { 

    public SwingTest() { 
     initComponents(); 
    } 

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

      @Override 
      public void run() { 
       new SwingTest().setVisible(true); 
      } 
     }); 
    } 
    private JPanel panelCenter, panelCreating; 
    private JScrollPane scrollPaneCreating, scrollPaneCenter; 
    private JTextPane textPane1, textPane2; 
    private JButton button1; 

    private void initComponents() { 
     setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); 
     setMinimumSize(new Dimension(300, 300)); 

     panelCreating = new JPanel(); 
     panelCreating.setMinimumSize(new Dimension(160, 200)); 
     panelCreating.setPreferredSize(new Dimension(160, 200)); 
     scrollPaneCreating = new JScrollPane(panelCreating, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

     textPane1 = new JTextPane(); 
     textPane1.setText("a\na"); 
     textPane2 = new JTextPane(); 
     textPane2.setText("b\nb"); 
     button1 = new JButton("+++"); 

     panelCenter = new JPanel(); 
     panelCenter.setBackground(Color.blue); 
     scrollPaneCenter = new JScrollPane(panelCenter); 



     // ----------------- Left Panel Init ----------------------- 

     panelCreating.setLayout(new GridBagLayout()); 
     panelCreating.setBackground(Color.ORANGE); 
     panelCreating.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); 

     GridBagConstraints c = new GridBagConstraints(); 
     c.insets = new Insets(0, 0, 4, 4); 
     c.anchor = GridBagConstraints.FIRST_LINE_START; 
     c.weightx = c.weighty = 0; 

     c.gridx = 0; 
     c.gridy = GridBagConstraints.RELATIVE; 
     c.gridwidth = GridBagConstraints.REMAINDER; 
     c.gridheight = 1; 
     c.fill = GridBagConstraints.BOTH; 
     panelCreating.add(textPane1, c); 

     button1.addActionListener(new ActionListener() { 

      int height = 50; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       textPane1.setText(textPane1.getText() + "\na"); 
       textPane1.setPreferredSize(new Dimension(150, height)); 
       textPane2.setText(textPane2.getText() + "\nb"); 
       textPane2.setPreferredSize(new Dimension(150, height)); 
       height += 30; 

       panelCreating.revalidate(); 
       panelCreating.repaint(); 
       scrollPaneCreating.revalidate(); 
      } 
     }); 
     panelCreating.add(button1, c); 

     panelCreating.add(textPane2, c); 

     // ------------------------------------------------------- 

     getContentPane().setLayout(new GridBagLayout()); 
     c = new GridBagConstraints(); 

     c.ipadx = c.ipady = 0; 
     c.insets = new Insets(0, 0, 0, 0); 
     c.weighty = 0; 
     c.gridheight = 1; 
     c.gridx = 0; 
     c.gridy = 1; 
     c.gridwidth = 1; 
     c.weightx = 0; 
     c.fill = GridBagConstraints.BOTH; 
     getContentPane().add(scrollPaneCreating, c); 


     c.gridx = 1; 
     c.gridy = 1; 
     c.fill = GridBagConstraints.BOTH; 
     c.weightx = 1; 
     c.weighty = 1; 
     getContentPane().add(scrollPaneCenter, c); 

    } 
} 

bảng vàng cũng sử dụng GridBagLayout. Xin lỗi vì tiếng Anh của tôi

+2

Tại sao thanh cuộn ngang cho phép chính nó khi các thành phần trong vòng chỉ phát triển theo chiều dọc? Xin vui lòng bao gồm một [sscce] (http://www.sscce.org) vì nó không rõ ràng những gì bạn đang yêu cầu (ít nhất là với tôi). – mre

+0

Xin lỗi, ý tôi là thanh cuộn dọc .. – alaster

+1

@alaster, bạn có thể chỉnh sửa bài đăng của mình bằng mã trong http://sscce.org/ biểu mẫu không, vì đây có thể là bài học tại sao JScrollPane không hoạt động bằng cách sử dụng AbsoluteLayout, +1 cho ghi lại vấn đề lạ này – mKorbel

Trả lời

5

Thay vì thiết lập một kích thước ưa thích trên panelCreating, thiết lập nó trên scrollPaneCreating. Và không đặt kích thước ưa thích trên các thành phần văn bản, chúng sẽ phát triển khi bạn thêm các dòng văn bản mới vào chúng. Ý tưởng là để có bảng điều khiển bên trong ngăn cuộn phát triển lớn như nó cần, và chỉ giới hạn kích thước của cửa sổ cuộn chính nó.

// [...] 

    panelCreating = new JPanel(); 
    //panelCreating.setMinimumSize(new Dimension(160, 200)); 
    //panelCreating.setPreferredSize(new Dimension(160, 200)); 
    scrollPaneCreating = new JScrollPane(panelCreating, 
     JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
     JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
    scrollPaneCreating.setMinimumSize(new Dimension(160, 200)); 
    scrollPaneCreating.setPreferredSize(new Dimension(160, 200)); 

    // [...] 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      textPane1.setText(textPane1.getText() + "\na"); 
      //textPane1.setPreferredSize(new Dimension(150, height)); 
      textPane2.setText(textPane2.getText() + "\nb"); 
      //textPane2.setPreferredSize(new Dimension(150, height)); 
      //height += 30; 

      // This isn't necessary either 
      //panelCreating.revalidate(); 
      //panelCreating.repaint(); 
      //scrollPaneCreating.revalidate(); 
     } 

Edited thêm: thay thế khác là để thiết lập kích thước trên JViewport đó được gắn vào ô cuộn. Chế độ xem là nơi hiển thị nội dung. Bạn có thể loại suy nghĩ của cửa sổ cuộn như được bao gồm các khung nhìn cộng với thanh cuộn. Nếu ngăn cuộn được đặt thành kích thước cố định, thì kích thước khung nhìn được xác định bằng cách trừ kích thước thanh cuộn. Nhưng nếu chế độ xem được đặt thành kích thước cố định thì kích thước khung cuộn được xác định bằng cách thêm kích thước thanh cuộn vào kích thước khung nhìn. Đặt kích thước cố định trên chế độ xem là thích hợp hơn nếu bạn muốn kiểm soát chính xác lượng nội dung sẽ được hiển thị trên màn hình, vì kích thước thanh cuộn có thể khác nhau tùy theo hệ điều hành.

scrollPaneCreating.getViewport().setMinimumSize(new Dimension(160, 200)); 
scrollPaneCreating.getViewport().setPreferredSize(new Dimension(160, 200)); 
+0

Đó là sai lầm của tôi Và tôi thậm chí không cần thay đổi bố cục. – alaster

4

Bố cục mặc định là JPanelFlowLayout. Thay vào đó, hãy thử GridLayout. Có một ví dụ liên quan here. Ví dụ:

panelCreating = new JPanel(new GridLayout()); 
scrollPaneCreating = new JScrollPane(panelCreating); 

Phụ lục: Đồng thời xem xét bố cục lồng nhau. Ví dụ dưới đây sử dụng BoxLayout cho bảng điều khiển bên trái.

enter image description here

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.GridLayout; 
import javax.swing.BorderFactory; 
import javax.swing.Box; 
import javax.swing.BoxLayout; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextPane; 

/** @see https://stackoverflow.com/questions/9184476 */ 
public class SwingTest extends JFrame { 

    private static final int N = 8; 

    public SwingTest() { 
     initComponents(); 
    } 

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

      @Override 
      public void run() { 
       new SwingTest().setVisible(true); 
      } 
     }); 
    } 
    private JPanel panelCenter, panelCreating; 
    private JScrollPane scrollPaneCreating, scrollPaneCenter; 

    private void initComponents() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     panelCreating = new JPanel(); 
     scrollPaneCreating = new JScrollPane(panelCreating, 
      JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 

     panelCenter = new JPanel(); 
     panelCenter.setBackground(Color.blue); 
     scrollPaneCenter = new JScrollPane(panelCenter); 

     // ----------------- Left Panel Init ----------------------- 
     panelCreating.setLayout(new BoxLayout(panelCreating, BoxLayout.Y_AXIS)); 
     panelCreating.setBackground(Color.orange); 
     panelCreating.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); 

     panelCreating.add(createTextPane()); 
     panelCreating.add(Box.createVerticalStrut(N)); 
     panelCreating.add(createTextPane()); 
     panelCreating.add(Box.createVerticalStrut(N)); 
     panelCreating.add(createTextPane()); 

     // ------------------------------------------------------- 
     setLayout(new GridLayout(1, 0)); 
     add(scrollPaneCreating); 
     add(scrollPaneCenter); 
     pack(); 
    } 

    private JTextPane createTextPane() { 
     JTextPane pane = new JTextPane(); 
     pane.setText("" 
      + "Twas brillig and the slithy toves\n" 
      + "Did gyre and gimble in the wabe;\n" 
      + "All mimsy were the borogoves,\n" 
      + "And the mome raths outgrabe."); 

     pane.setBorder(BorderFactory.createEmptyBorder(N, N, N, N)); 
     return pane; 
    } 
} 
+0

Tôi chỉ sử dụng GridBagLayout Bảng bên trong và bên ngoài Nhưng khi tôi sử dụng 'GridLayout' trong SSCCE đính kèm, tôi có cùng một vấn đề .. – alaster

+0

Tôi đã hiển thị một phương pháp thay thế ở trên. – trashgod

+0

thay thế tốt đẹp + 1 – mKorbel

0

Tôi đã khắc phục sự cố của bạn khi thêm 1 dòng.

panelCreating.setPreferredSize(new Dimension((int) panelCreating.getPreferredSize().getWidth(), 
        (int)(panelCreating.getPreferredSize().getHeight()+30))); 

Dòng phải được chèn sau các dòng sau;

@Override 
     public void actionPerformed(ActionEvent e) { 
      textPane1.setText(textPane1.getText() + "\na"); 
      textPane1.setPreferredSize(new Dimension(150, height)); 
      textPane2.setText(textPane2.getText() + "\nb"); 
      textPane2.setPreferredSize(new Dimension(150, height)); 
      height += 30; 

Giải thích: Cái túi bố trí lưới không đặt nó pane ưa thích kích thước khi bạn thiết lập kích thước ưa thích của textPanes bên trong nó, nhưng ScrollPane chỉ cuộn dựa trên kích thước ưa thích của cửa sổ trong đó. Vì vậy, bạn phải đặt kích thước ưa thích mới của cửa sổ mỗi khi bạn thay đổi kích thước của các thành phần trong đó, sau đó scrollPane sẽ biết chính xác những gì anh ta phải làm. Đó là những gì tôi đã làm, thêm một dòng để tăng kích thước ưa thích của createPanel, là một trong những scrollPanel

Các vấn đề liên quan