2011-01-15 21 views
9

Tôi đang làm việc trên một giao diện đồ họa lớn hơn với Java và tôi trở nên tức giận về Trình quản lý bố cục.Làm thế nào để thiết lập kích thước thành phần với GridLayout? Có cách nào tốt hơn?

Tôi có "Bảng điều khiển cài đặt" với số lượng JComponents thay đổi trong đó (Nhãn, Nút, JSpinners, JSliders, ...). Tôi chỉ muốn những điều sau:

JLabel < -> JComponent

JLabel < -> JComponent

JLabel < -> JComponent

...

Bảng điều chỉnh của tôi có một kích thước của 500px, để có đủ không gian cho rất nhiều thành phần. Thật không may GridLayout luôn luôn kéo dài kích thước của các thành phần cho toàn bộ bảng điều khiển, ngay cả khi tôi thiết lập một MaximumSize cho mỗi thành phần. Có vẻ ngu ngốc nếu chỉ có hai nút, mỗi nút có chiều cao 250px.

Tôi đã thử Bố cục luồng nhưng tôi không thể tìm ra cách để tạo các dòng mới một cách chính xác. Tôi đã thử BoxLayout.Y_AXIS, nhưng các thành phần luôn được căn giữa, và Label và Component không nằm trong cùng một dòng.

Có ai biết cách tốt và ngắn gọn với LayoutManagers để xử lý đúng cách không?

+0

Bạn đã bao giờ nhận được phản hồi tốt về điều này chưa? Ban đầu tôi đã sử dụng BoxLayout và chạy vào vấn đề chính xác này, vì vậy mọi người đã nói với tôi sử dụng GridLayout, và tôi nhận được cùng một vấn đề như bạn ở trên. Bây giờ các bình luận của bạn nói để đi đến GridBagLayout. Giải pháp thực tế là gì? – theJollySin

+1

Thật không may tôi không bao giờ có bất kỳ câu trả lời tốt hơn so với những ở đây. Tôi nghĩ rằng cuối cùng tôi đã sử dụng GridBagLayout, nhưng hiện tại tôi không có nhiều trong Java GUI. – Blackbam

+0

Cuối cùng, giải pháp duy nhất có hiệu quả đối với tôi là tự thiết lập vị trí của mọi thứ. Nó không phải là khó khăn, và nó làm cho tôi nghĩ rằng tất cả các bố trí đặt trước thực sự là rất hạn chế sử dụng trường hợp. – theJollySin

Trả lời

4

Không sử dụng GridLayout cho điều gì đó không có nghĩa là phải làm. Nó âm thanh với tôi như GridBagLayout sẽ là một phù hợp hơn cho bạn, hoặc là hoặc MigLayout (mặc dù bạn sẽ phải tải về đầu tiên vì nó không phải là một phần của tiêu chuẩn Java). Hoặc là hoặc kết hợp các trình quản lý bố cục như BoxLayout cho các dòng và GridLayout để giữ tất cả các hàng.

Ví dụ, sử dụng GridBagLayout:

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

public class LayoutEg1 extends JPanel{ 
    private static final int ROWS = 10; 

    public LayoutEg1() { 
     setLayout(new GridBagLayout()); 
     for (int i = 0; i < ROWS; i++) { 
      GridBagConstraints gbc = makeGbc(0, i); 
      JLabel label = new JLabel("Row Label " + (i + 1)); 
      add(label, gbc); 

      JPanel panel = new JPanel(); 
      panel.add(new JCheckBox("check box")); 
      panel.add(new JTextField(10)); 
      panel.add(new JButton("Button")); 
      panel.setBorder(BorderFactory.createEtchedBorder()); 
      gbc = makeGbc(1, i); 
      add(panel, gbc); 
     } 
    } 

    private GridBagConstraints makeGbc(int x, int y) { 
     GridBagConstraints gbc = new GridBagConstraints(); 
     gbc.gridwidth = 1; 
     gbc.gridheight = 1; 
     gbc.gridx = x; 
     gbc.gridy = y; 
     gbc.weightx = x; 
     gbc.weighty = 1.0; 
     gbc.insets = new Insets(5, 5, 5, 5); 
     gbc.anchor = (x == 0) ? GridBagConstraints.LINE_START : GridBagConstraints.LINE_END; 
     gbc.fill = GridBagConstraints.HORIZONTAL; 
     return gbc; 
    } 

    private static void createAndShowUI() { 
     JFrame frame = new JFrame("Layout Eg1"); 
     frame.getContentPane().add(new LayoutEg1()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 
2

Bạn cần phải thử một trong các cách sau:

  1. GridBagLayout
  2. MigLayout
  3. SpringLayout

Chúng cung cấp nhiều tính năng hơn và sẽ dễ dàng hơn để có được những gì bạn đang tìm kiếm.

4

Đối với bố cục phức tạp hơn, tôi thường sử dụng GridBagLayout, phức tạp hơn, nhưng đó là giá. Hôm nay, tôi có thể sẽ kiểm tra MiGLayout.

12

Thay thế cho bố cục khác, có thể đặt bảng điều khiển của bạn bằng GridLayout, bên trong bảng điều khiển khác là FlowLayout. Bằng cách đó, khoảng cách của bạn sẽ còn nguyên vẹn nhưng sẽ không mở rộng trên toàn bộ không gian có sẵn.

+1

+1, vâng, bạn không bao giờ bị buộc phải chỉ sử dụng một trình quản lý bố cục đơn lẻ. Một mẹo đơn giản như thế này có thể giúp ích trong nhiều trường hợp. – camickr

+0

Câu trả lời này là tuyệt vời trong sự đơn giản của nó, làm việc hoàn hảo cho tôi quá, ngoài việc để đối phó với một số liên kết ngang issuses tôi đặt GridLayout của tôi bên trong một BoxLayout thay vì một FlowLayout, nhưng nguyên tắc tương tự. – nigelg

3

Trong dự án của tôi, tôi quản lý để sử dụng GridLayout và kết quả rất ổn định, không có nhấp nháy và với một thanh cuộn dọc hoàn toàn làm việc.

Trước tiên, tôi đã tạo một JPanel cho cài đặt; trong trường hợp của tôi nó là một lưới với một hàng cho mỗi tham số và hai cột: cột bên trái là cho các nhãn và cột bên phải là cho các thành phần. Tôi tin rằng trường hợp của bạn là tương tự.

JPanel yourSettingsPanel = new JPanel(); 
yourSettingsPanel.setLayout(new GridLayout(numberOfParams, 2)); 

Sau đó, tôi điền bảng này bằng cách lặp lại các tham số và thay đổi giữa thêm một JLabel và thêm thành phần.

for (int i = 0; i < numberOfParams; ++i) { 
    yourSettingsPanel.add(labels[i]); 
    yourSettingsPanel.add(components[i]); 
} 

Để ngăn các thiết lập của bạnPanel mở rộng ra toàn bộ vùng chứa Trước tiên, tôi quấn nó ở khu vực phía bắc của bảng giả, mà tôi gọi là northOnlyPanel.

JPanel northOnlyPanel = new JPanel(); 
northOnlyPanel.setLayout(new BorderLayout()); 
northOnlyPanel.add(yourSettingsPanel, BorderLayout.NORTH); 

Cuối cùng, tôi bọc phía bắcOnlyPanel trong JScrollPane, hoạt động tốt đẹp ở mọi nơi.

JScrollPane scroll = new JScrollPane(northOnlyPanel, 
            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 

Rất có thể bạn muốn hiển thị JScrollPane này được mở rộng bên trong JFrame; bạn có thể thêm nó vào một BorderLayout JFrame, trong khu vực TRUNG TÂM:

window.add(scroll, BorderLayout.CENTER); 

Trong trường hợp của tôi, tôi đặt nó trên cột bên trái của một GridLayout (1, 2) bảng điều khiển, và tôi sử dụng các cột bên phải để hiển thị theo ngữ cảnh trợ giúp cho mỗi tham số.

JTextArea help = new JTextArea(); 
help.setLineWrap(true); 
help.setWrapStyleWord(true); 
help.setEditable(false); 

JPanel split = new JPanel(); 
split.setLayout(new GridLayout(1, 2)); 
split.add(scroll); 
split.add(help); 
+0

Sự kết hợp của GridLayout bên trong BorderLayout hoạt động rất tốt để có được các tính năng của GridLayout mà không cần kéo dài nội dung của nó một cách bất thường. Ý tưởng tốt! – David

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