2011-11-26 44 views
5

Tôi có một số JFrame chứa một bộ JPanels trong một số CardLayout. Mỗi JPanel có kích thước khác và tôi muốn JFrame để thích ứng với kích thước của JPanel hiện tại (không phải là JPanel để thích ứng với kích thước của JFrame).Cách đặt kích thước JFrame để phù hợp với CardLayout được hiển thị JPanel?

Tôi làm cách nào để đạt được điều này?

+2

* "Tôi muốn JFrame thích nghi với kích thước của JPanel hiện đang được hiển thị" * Sẽ cảm thấy lạ khi người dùng có kích thước thay đổi khung hình chỉ vì thay đổi nội dung được hiển thị. –

+0

Có kích thước sửa lỗi JFrame khá xấu khi bảng điều khiển bên trong không khớp. Tôi đã thử nó. – JVerstry

+0

Tôi không chắc chắn điều này sẽ làm việc nhưng bạn có thể thử điều này: 'frame.setSize (bảng điều khiển.getPreferredSize()); ' –

Trả lời

11

Tổng là: nếu bạn có một vấn đề bố trí, luôn giải quyết nó với một LayoutManager thích hợp. Không bao giờ tinh chỉnh gợi ý định kích thước của một thành phần để đạt được mục tiêu của bạn.

Trong trường hợp này, việc điều chỉnh CardLayout rất dễ dàng. Theo mặc định, nó tính toán prefSize của nó đến tối đa prefSizes của tất cả các thẻ. Đơn giản chỉ cần phân lớp và thực hiện để trả lại prefSize (cộng insets) của thẻ hiện thời hiển thị:

public static class MyCardLayout extends CardLayout { 

    @Override 
    public Dimension preferredLayoutSize(Container parent) { 

     Component current = findCurrentComponent(parent); 
     if (current != null) { 
      Insets insets = parent.getInsets(); 
      Dimension pref = current.getPreferredSize(); 
      pref.width += insets.left + insets.right; 
      pref.height += insets.top + insets.bottom; 
      return pref; 
     } 
     return super.preferredLayoutSize(parent); 
    } 

    public Component findCurrentComponent(Container parent) { 
     for (Component comp : parent.getComponents()) { 
      if (comp.isVisible()) { 
       return comp; 
      } 
     } 
     return null; 
    } 

} 

dùng đó (vay @ dụ mKorbel của), phương pháp chính sạch co lại xuống:

private static void createAndShowUI() { 
    final CardLayout cardLayout = new MyCardLayout(); 
    final JPanel cardHolder = new JPanel(cardLayout); 
    final JFrame frame = new JFrame("MultiSizedPanels"); 
    JLabel[] labels = { 
     new JLabel("Small Label", SwingConstants.CENTER), 
     new JLabel("Medium Label", SwingConstants.CENTER), 
     new JLabel("Large Label", SwingConstants.CENTER)}; 

    for (int i = 0; i < labels.length; i++) { 
     int padding = 50 * (i + 1); 
     Border lineBorder = BorderFactory.createCompoundBorder(
      BorderFactory.createLineBorder(Color.blue), 
      BorderFactory.createEmptyBorder(padding, padding, padding, padding)); 
     labels[i].setBorder(lineBorder); 
     JPanel containerPanel = new JPanel(); 
     containerPanel.add(labels[i]); 
     cardHolder.add(containerPanel, String.valueOf(i)); 
    } 
    JButton nextButton = new JButton("Next"); 
    nextButton.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      cardLayout.next(cardHolder); 
      frame.pack(); 
     } 
    }); 
    JPanel btnHolder = new JPanel(); 
    btnHolder.add(nextButton); 

    frame.add(cardHolder, BorderLayout.CENTER); 
    frame.add(btnHolder, BorderLayout.SOUTH); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.pack(); 
    frame.setLocation(150, 150); 
    frame.setVisible(true); 
} 
+0

Cảm ơn. Đó là sạch hơn và chính xác những gì tôi muốn. – JVerstry

+0

bây giờ là thế giới rõ ràng và đẹp hơn +1 – mKorbel

+0

Vì vậy, làm sạch mà tôi không thể tin được. Cảm ơn! –

2

Tôi nghĩ rằng bạn có thể có trình quản lý bố cục sai cho những gì bạn muốn làm (bỏ qua một bên, vì tôi không chắc bạn muốn làm những gì bạn muốn làm).

Tôi chưa tìm thấy tài liệu về những gì tôi nghi ngờ, đó là CardLayout định lại kích thước tất cả các con của nó thành kích thước của vùng chứa. Tôi đã tìm thấy những nhận xét sau đây cho phương pháp "layoutContainer" của nó:

  * Each component in the <code>parent</code> container is reshaped 
     * to be the size of the container, minus space for surrounding 
     * insets, horizontal gaps, and vertical gaps. 

Tôi nghĩ rằng đây là hành vi hợp lý, vì nó sẽ rất khó chịu cho người dùng để có nhảy kích thước bảng điều khiển xung quanh như tấm nằm ngang.

Nếu đây thực sự là hành vi bạn muốn, thì tôi nghĩ bạn muốn có một trình quản lý bố cục khác. Và vì đó là hành vi bất thường đối với giao diện người dùng nói chung, bạn cũng có thể không tìm thấy một tiêu chuẩn để thực hiện 'tính năng' cụ thể này, vì vậy bạn có thể phải viết riêng của mình.

4

Đây là SSCCE.

1) Để tăng/giảm kích thước liên tục, bạn nên tìm một số API hoạt ảnh.

hoặc

2) Nếu không có bất kỳ tác vụ chạy nền với sản lượng để GUI, bạn có thể tạm dừng trong khi kích thước các JFrame. Trong trường hợp đó, bạn sẽ trì hoãn việc tăng/giảm bằng cách sử dụng Thread#sleep(int) được đưa vào chuỗi Runnable.

3) Thông báo (không phải cho OP) sử dụng Thread#sleep(int) trực tiếp trong EDT sẽ đóng băng GUI cho đến khi kết thúc chậm trễ.

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.border.Border; 
//based on HFOE http://stackoverflow.com/questions/5414177/change-size-of-jpanel-using-cardlayout/5414770#5414770 
public class MultiSizedPanels { 

    private static void createAndShowUI() { 
     final CardLayout cardLayout = new CardLayout(); 
     final JPanel cardHolder = new JPanel(cardLayout); 
     final JFrame frame = new JFrame("MultiSizedPanels"); 
     JLabel[] labels = { 
      new JLabel("Small Label", SwingConstants.CENTER), 
      new JLabel("Medium Label", SwingConstants.CENTER), 
      new JLabel("Large Label", SwingConstants.CENTER)}; 

     for (int i = 0; i < labels.length; i++) { 
      int padding = 50; 
      Dimension size = labels[i].getPreferredSize(); 
      size = new Dimension(size.width + 2 * (i + 1) * padding, size.height + 2 * (i + 1) * padding); 
      labels[i].setPreferredSize(size); 
      Border lineBorder = BorderFactory.createLineBorder(Color.blue); 
      labels[i].setBorder(lineBorder); 
      JPanel containerPanel = new JPanel(); 
      if (i == 1) { 
       containerPanel.setPreferredSize(new Dimension(300, 200)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } else if (i == 2) { 
       containerPanel.setPreferredSize(new Dimension(600, 400)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } else { 
       containerPanel.setPreferredSize(new Dimension(800, 600)); 
       containerPanel.add(labels[i], BorderLayout.CENTER); 
       cardHolder.add(containerPanel, String.valueOf(i)); 
      } 
     } 
     JButton nextButton = new JButton("Next"); 
     nextButton.addActionListener(new ActionListener() { 

      public void actionPerformed(ActionEvent e) { 
       cardLayout.next(cardHolder); 
       Dimension dim = new Dimension(); 
       for (Component comp : cardHolder.getComponents()) { 
        if (comp.isVisible() == true) { 
         dim = comp.getPreferredSize(); 
        } 
       } 
       frame.setPreferredSize(dim); 
       java.awt.EventQueue.invokeLater(new Runnable() { 

        public void run() { 
         frame.pack(); 
        } 
       }); 
      } 
     }); 
     JPanel btnHolder = new JPanel(); 
     btnHolder.add(nextButton); 

     frame.add(cardHolder, BorderLayout.CENTER); 
     frame.add(btnHolder, BorderLayout.SOUTH); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocation(150, 150); 
     frame.setVisible(true); 
    } 

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

      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 
+0

-1 vì sử dụng quá nhiều setPrefSize: quy tắc chung là (như bạn biết rõ :-) để giải quyết các vấn đề định cỡ bằng cách sử dụng Trình quản lý bố cục phù hợp. Nếu bạn không tìm thấy nó đang làm những gì bạn muốn, hãy viết/điều chỉnh một LayoutManager mà ... – kleopatra

0
Try this code this may help you. 




protected void paintComponent(Graphics g) { 
if (getModel().isArmed()) { 
     g.setColor(Color.lightGray); 
} else { 
    g.setColor(getBackground()); 
} 
g.fillOval(0, 0, getSize().width-1, getSize().height-1); 
System.out.println("width is "+getSize().width+"height is "+getSize().height); 
super.paintComponent(g); 
} 
protected void paintBorder(Graphics g) { 
g.setColor(getForeground()); 
g.drawOval(0, 0, getSize().width-1, getSize().height-1); 
} 
Shape shape; 
public boolean contains(int x, int y) { 
if (shape == null || !shape.getBounds().equals(getBounds())) { 
    shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight()); 
} 
return shape.contains(x, y); 
}} 
Các vấn đề liên quan