2013-09-25 42 views
5

Tôi cần gán chiều rộng cố định cho một vài cột của JTable và sau đó chiều rộng bằng nhau cho tất cả các cột khác.Đặt chiều rộng cột của JTable theo phần trăm

Giả sử một JTable có 5 cột. Cột đầu tiên phải có chiều rộng là 100 và cột thứ hai có chiều rộng là 150. Nếu chiều rộng còn lại của JTable là 600 sau khi đặt chiều rộng của hai cột, tôi muốn chia đều cho ba cột còn lại.

Vấn đề là table.getParent().getSize().width thường là 0, ngay cả khi nó được thêm vào JFrame và hiển thị, vì vậy tôi không thể sử dụng nó làm cơ sở.

Tôi làm cách nào để thực hiện việc này?

+2

Nếu câu trả lời phù hợp với bạn, hãy chấp nhận câu trả lời. – Astrobleme

Trả lời

3

Tôi nghĩ bạn cần sử dụng table.getPreferredSize() để thay thế. Hãy thử đoạn mã này:

import java.awt.Dimension; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.SwingUtilities; 
import javax.swing.table.DefaultTableModel; 


public class Tests { 

    private void initGUI(){   
     Object[] tableHeader = new Object[]{"Name", "Category", "Color","Ranking"}; 
     DefaultTableModel dftm = new DefaultTableModel(tableHeader, 0);   
     dftm.addRow(new Object[]{"Watermelon","Fruit","Green and red",3}); 
     dftm.addRow(new Object[]{"Tomato","Vegetable","Red",5}); 
     dftm.addRow(new Object[]{"Carrot","Vegetable","Orange",2}); 

     JTable table = new JTable(dftm); 

     JScrollPane scrollPane = new JScrollPane(); 
     scrollPane.setViewportView(table); 

     Dimension tableSize = table.getPreferredSize(); 
     table.getColumn("Name").setPreferredWidth(100); 
     table.getColumn("Category").setPreferredWidth(150); 
     table.getColumn("Color").setPreferredWidth(Math.round((tableSize.width - 250)* 0.70f)); 
     table.getColumn("Ranking").setPreferredWidth(Math.round((tableSize.width - 250)* 0.30f)); 

     JFrame frame = new JFrame("Demo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(scrollPane); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Tests().initGUI(); 
      } 
     });   

    } 
} 

Như bạn sẽ thấy, Name cột sẽ có chiều rộng 100, Category sẽ có chiều rộng 150, Color cột sẽ phù hợp tại 70% chiều rộng dư và Ranking sẽ phù hợp tại 30% cuối cùng.

Cập nhật

Dựa trên nhận xét này:

Cảm ơn, nhưng điều này sẽ không hoạt động nếu kích thước của JFrame được thiết lập một cách rõ ràng lớn hơn so với JTable ...

Giải pháp có thể được chơi với các phương pháp setMinWidthsetMaxWidth để sửa chiều rộng cột tĩnh hoặc bạn có thể triển khaicủa riêng mình. Trong ví dụ trên thay setPreferredWith dòng như sau và cố gắng kích thước ưa thích thiết lập khung như bạn muốn:

final JTable table = new JTable(dftm);   
    table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { 

     @Override 
     public void columnAdded(TableColumnModelEvent e) { 
      table.columnAdded(e); 
     } 

     @Override 
     public void columnRemoved(TableColumnModelEvent e) { 
      table.columnRemoved(e); 
     } 

     @Override 
     public void columnMoved(TableColumnModelEvent e) { 
      table.columnMoved(e); 
     } 

     @Override 
     public void columnMarginChanged(ChangeEvent e) { 
      Dimension tableSize = table.getSize(); 
      table.getColumn("Name").setWidth(100); 
      table.getColumn("Category").setWidth(150); 
      table.getColumn("Color").setWidth(Math.round((tableSize.width - 250)* 0.70f)); 
      table.getColumn("Ranking").setWidth(Math.round((tableSize.width - 250)* 0.30f)); 
     } 

     @Override 
     public void columnSelectionChanged(ListSelectionEvent e) { 
      table.columnSelectionChanged(e); 
     } 
    }); 
+0

Cảm ơn, nhưng điều này sẽ không hoạt động nếu kích thước của JFrame được đặt rõ ràng lớn hơn JTable ... –

+1

Tôi thấy quan điểm của bạn. Điều gì về việc chơi với các phương thức 'setMinWidth' và' setMaxWidth'? Ví dụ cho cột đầu tiên của bạn, bạn có thể gọi 'setMinWidth (100)' và 'setMaxWidth (100)'. Chiều rộng của nó sẽ luôn luôn là 100 bất kể kích thước của khung hình và thậm chí trên kích thước của khung hình. – dic19

+0

@TomTucker vui lòng xem câu trả lời cập nhật. – dic19

5

tôi cần phải gán một chiều rộng cố định vào một vài cột của một JTable và sau đó có chiều rộng bình đẳng cho tất cả các các cột khác.

Để chế độ thay đổi kích thước của bảng hoạt động cho bạn. Thiết lập chế độ thay đổi kích thước cho tất cả các cột và thiết lập các min/giá trị tối đa của các cột cố định:

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

public class TableLayout extends JPanel 
{ 
    public TableLayout() 
    { 
     setLayout(new BorderLayout()); 

     JTable table = new JTable(5, 7); 
     add(new JScrollPane(table)); 

     table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); 
     TableColumn columnA = table.getColumn("A"); 
     columnA.setMinWidth(100); 
     columnA.setMaxWidth(100); 
     TableColumn columnC = table.getColumn("C"); 
     columnC.setMinWidth(50); 
     columnC.setMaxWidth(50); 
    } 

    private static void createAndShowUI() 
    { 
     JFrame frame = new JFrame("TableLayout"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(new TableLayout()); 
     frame.setSize(600, 200); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

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

+1: 'column.setPreferredWidth()' không hoạt động khi chế độ thay đổi kích thước là 'AUTO_RESIZE_ALL_COLUMNS' vì vậy' setMin/MaxWidth() 'phải được sử dụng. – Matthieu

0

tôi phải tự động thiết lập các cột bảng của tôi chiều rộng cho một dự án mà đã có để hiển thị một cách chính xác về độ phân giải màn hình cài đặt DPI khác nhau. Ý tưởng cho giải pháp của tôi đến từ câu trả lời của dic19s.

Về cơ bản tôi có kích thước ưa thích của JPanel, nơi JSrollPane của JTable được đặt và hoạt động tốt. Xin vui lòng xem bên dưới

Dimension tableSize = tableScrollPanePanel.getPreferredSize(); 
table.getColumnModel().getColumn(0).setPreferredWidth(Math.round(tableSize.width*0.35f)); 
table.getColumnModel().getColumn(1).setPreferredWidth(Math.round(tableSize.width*0.215f)); 
table.getColumnModel().getColumn(2).setPreferredWidth(Math.round(tableSize.width*0.20f)); 
table.getColumnModel().getColumn(3).setPreferredWidth(Math.round(tableSize.width*0.10f)); 
table.getColumnModel().getColumn(4).setPreferredWidth(Math.round(tableSize.width*0.10f)); 

Hope this helps ai đó

Cảm ơn

9
public MyJFrame() { 
    initComponents(); 
    resizeColumns(); 
    addComponentListener(new ComponentAdapter() { 
     @Override 
     public void componentResized(ComponentEvent e) { 
      resizeColumns(); 
     } 
    }); 
} 
//SUMS 100% 
float[] columnWidthPercentage = {20.0f, 55.0f, 10.0f, 5.0f, 5.0f, 5.0f}; 

private void resizeColumns() { 
    int tW = jTable1.getWidth(); 
    TableColumn column; 
    TableColumnModel jTableColumnModel = jTable1.getColumnModel(); 
    int cantCols = jTableColumnModel.getColumnCount(); 
    for (int i = 0; i < cantCols; i++) { 
     column = jTableColumnModel.getColumn(i); 
     int pWidth = Math.round(columnWidthPercentage[i] * tW); 
     column.setPreferredWidth(pWidth); 
    } 
} 
+1

Đây là câu trả lời hay nhất tôi đã thấy :) –

+0

Lưu ý rằng bạn có thể sử dụng ['TableColumnModel.getTotalColumnWidth()'] (https://docs.oracle.com/javase/7/docs/api/javax/swing/table /TableColumnModel.html#getTotalColumnWidth()) trong trường hợp bảng của bạn được bao gồm trong một 'JScrollPane' (thường là trường hợp). – Matthieu

+0

ít muộn cho bữa tiệc nhưng columnWidthPercentage nên thêm tối đa 1.0, nếu không bảng của bạn sẽ phát triển rất nhanh –

0

Nó nghĩ rằng nó sẽ được dễ dàng hơn để sử dụng (và tái sử dụng) thành phần tương đối thay đổi kích thước nếu chúng ta rút gọn trong một riêng lớp học.Vì tôi cũng đã phải đối mặt với cùng một vấn đề, tôi muốn đăng mã của tôi ở đây.

Từ góc độ khách hàng Tôi muốn làm điều gì đó như thế này

TableColumnModel columnModel = jTable.getColumnModel(); 

TableColumn firstColumn = columnModel.getColumn(0); 
TableColumn secondColumn = columnModel.getColumn(1); 

ComponentResize<TableColumn> columnResize = new TableColumnResize(); 
RelativeWidthResizer<TableColumn> relativeWidthResizer = new RelativeWidthResizer<TableColumn>(columnResize); 

relativeWidthResizer.setRelativeWidth(firstColumn, 0.8); 
relativeWidthResizer.setRelativeWidth(secondColumn, 0.2); 

jTable.addComponentListener(relativeWidthResizer); 

Vì vậy, đầu tiên tôi định nghĩa giao diện ComponentResize và thực hiện một TableColumnResize

public interface ComponentResize<T> { 
    public void setWidth(T component, int width); 
} 

public class TableColumnResize implements ComponentResize<TableColumn> { 

    public void setWidth(TableColumn component, int width) { 
     component.setPreferredWidth(width); 
    } 
} 

Giao diện ComponentResize tách riêng cách kích thước của một thành phần được đặt từ API cụ thể. Ví dụ. một TableColumn 'width s có thể được thiết lập thông qua setPreferredWidth(int) trong khi một JComponent' kích thước s có thể được thiết lập bởi setPreferredWidth(Dimension)

Thần I thực hiện các RelativeWidthResizer mà đóng gói logic tính toán chiều rộng tương đối.

public class RelativeWidthResizer<T> extends ComponentAdapter { 

    private Map<T, Double> relativeWidths = new HashMap<T, Double>(); 
    private ComponentResize<T> componentResize; 

    public RelativeWidthResizer(ComponentResize<T> componentResize) { 
     this.componentResize = componentResize; 
    } 

    public void setRelativeWidth(T component, double relativeWidth) { 
     if (relativeWidth < 0.0) { 
      throw new IllegalArgumentException(
        "Relative width must be greater or equal to 0.0"); 
     } 

     if (relativeWidth > 1.0) { 
      throw new IllegalArgumentException(
        "Relative width must be less or equal to 1.0"); 
     } 

     double totalRelativeWidth = 0.0; 
     for (Double relativeComponentWidth : relativeWidths.values()) { 
      totalRelativeWidth += relativeComponentWidth.doubleValue(); 
     } 

     double availableRelativeWidth = 1.0d - (totalRelativeWidth + relativeWidth); 

     boolean totalPercentageExceeded = availableRelativeWidth < 0; 
     if (totalPercentageExceeded) { 
      double remainingRelativeWidth = 1.0d - totalRelativeWidth; 
      String message = MessageFormat.format(
        "Can't set component's relative width to {0}." 
          + " {1} relative width remaining", relativeWidth, 
        remainingRelativeWidth); 
      throw new IllegalArgumentException(message); 
     } 

     relativeWidths.put(component, relativeWidth); 
    } 

    @Override 
    public void componentResized(ComponentEvent e) { 
     Component component = e.getComponent(); 
     apply(component); 
    } 

    public void apply(Component baseComponent) { 
     Dimension size = baseComponent.getSize(); 
     int maxWidth = (int) size.getWidth(); 

     int remaining = maxWidth; 

     Set<Entry<T, Double>> entrySet = relativeWidths.entrySet(); 
     Iterator<Entry<T, Double>> entrySetIter = entrySet.iterator(); 

     while (entrySetIter.hasNext()) { 
      Entry<T, Double> componentEntry = entrySetIter.next(); 
      T componentToResize = componentEntry.getKey(); 
      Double relativeWidth = componentEntry.getValue(); 

      int width = (int) (maxWidth * relativeWidth.doubleValue()); 
      remaining -= width; 

      boolean lastComponent = !entrySetIter.hasNext(); 
      if (lastComponent && remaining > 0) { 
       width += remaining; 
      } 
      componentResize.setWidth(componentToResize, width); 
     } 
    } 
} 
Các vấn đề liên quan