2012-10-22 12 views
11

回答https://stackoverflow.com/a/5820366http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/を使用していますが、それは機能しますが、頻繁に列のサイズが広すぎたり狭すぎたりします。JTableの列を列のセルに最も長い内容に合わせるように調整する方法

テーブルにHTMLまたはテキストを入力しても問題ありません。

オラクルのドキュメントに標準TableModelを使用しています。

FormLayout currentEventLayout = new FormLayout(
      "fill:p", 
      "pref, pref"); 
PanelBuilder currentEventBuilder = new PanelBuilder(currentEventLayout); 
currentEventBuilder.add(mainQuotesTable.getTableHeader(), constraints.xy(1, 1)); 
currentEventBuilder.add(mainQuotesTable, constraints.xy(1, 2)); 

HTMLの例:

"<html><pre><font size=+1 face='Arial'>" + firstValue + "\n" + secondValue + "</font></pre></html>" 

シンプル行:ここで

firstValue + " - " + secondValue 

リサイズモード= JTable.AUTO_RESIZE_OFF私tabelの

コンテナなJGoodiesですt彼は例:

public class TableAdjustExample { 
private static JTable mainTable; 
private static Random random = new Random(); 

private static List<Data> data; 

private static class Data { 
    String name; 
    String surname; 

    private Data(String name, String surname) { 
     this.name = name; 
     this.surname = surname; 
    } 
} 

public static void main(String[] args) { 
    data = stubProvider(); 

    final JFrame frame = new JFrame("table adjust example"); 
    frame.add(createUI()); 
    frame.pack(); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
    frame.setSize(350, 400); 
    frame.setVisible(true); 

    update(); 
    java.util.Timer timer = new java.util.Timer(); 
    timer.schedule(new TimerTask() { 
     @Override 
     public void run() { 
      update(); 
     } 
    }, 3000, 3000); 
} 

private static JPanel createUI() { 
    JPanel jPanel = new JPanel(); 
    mainTable = new JTable(2, 3); 
    mainTable.setModel(new AbstractTableModel() { 
     @Override 
     public int getRowCount() { 
      return data.size(); 
     } 

     @Override 
     public int getColumnCount() { 
      return 2; 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      Data dataItem = data.get(rowIndex); 
      if (columnIndex == 0) { 
       return dataItem.name; 
      } 
      if (columnIndex == 1) { 
       return dataItem.surname; 
      } 
      throw new IllegalStateException(); 
     } 
    }); 
    mainTable.setGridColor(Color.black); 
    mainTable.setShowHorizontalLines(false); 
    mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 

    final TableCellRenderer defaultRenderer = mainTable.getTableHeader().getDefaultRenderer(); 
    mainTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() { 
     @Override 
     public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int column) { 
      JLabel parent = (JLabel) defaultRenderer.getTableCellRendererComponent(jTable, o, b, b1, row, column); 
      if (column == 0) { 
       parent.setText("name"); 
      } else { 
       parent.setText("surname"); 
      } 
      return parent; 
     } 
    }); 

    jPanel.add(mainTable.getTableHeader()); 
    jPanel.add(mainTable); 

    return jPanel; 
} 

private static void update() { 
    System.out.println("updating"); 
    data = stubProvider(); 

    adjustJTableRowSizes(mainTable); 
    for (int i = 0; i < mainTable.getColumnCount(); i++) { 
     adjustColumnSizes(mainTable, i, 2); 
    } 
} 

private static void adjustJTableRowSizes(JTable jTable) { 
    for (int row = 0; row < jTable.getRowCount(); row++) { 
     int maxHeight = 0; 
     for (int column = 0; column < jTable.getColumnCount(); column++) { 
      TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column); 
      Object valueAt = jTable.getValueAt(row, column); 
      Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column); 
      int heightPreferable = tableCellRendererComponent.getPreferredSize().height; 
      maxHeight = Math.max(heightPreferable, maxHeight); 
     } 
     jTable.setRowHeight(row, maxHeight); 
    } 

} 

public static void adjustColumnSizes(JTable table, int column, int margin) { 
    DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); 
    TableColumn col = colModel.getColumn(column); 
    int width; 

    TableCellRenderer renderer = col.getHeaderRenderer(); 
    if (renderer == null) { 
     renderer = table.getTableHeader().getDefaultRenderer(); 
    } 
    JLabel comp = (JLabel) renderer.getTableCellRendererComponent(
      table, col.getHeaderValue(), false, false, 0, 0); 
    width = comp.getPreferredSize().width; 

    for (int r = 0; r < table.getRowCount(); r++) { 
     renderer = table.getCellRenderer(r, column); 
     comp = (JLabel) renderer.getTableCellRendererComponent(
       table, table.getValueAt(r, column), false, false, r, column); 
     int currentWidth = comp.getPreferredSize().width; 
     width = Math.max(width, currentWidth); 
    } 

    width += 2 * margin; 

    col.setPreferredWidth(width); 
} 

private static List<Data> stubProvider() { 
    List<Data> data = new ArrayList<Data>(); 
    for (int i = 0; i < 4; i++) { 
     data.add(new Data(
       "<html>" + 
         "<div style='font-size: 15px'>Jason</div>" + 
         "<div style='font-size: 15px'>" + random.nextInt() + "</div>" + 
         "</html>", 
       "Statham " + random.nextInt())); 
    } 
    return data; 
} 
} 

私は行の高さ調整で、このような問題を抱えています。 <br>固定行調整の代わりに<pre>\n</pre>を使用する。

+0

の読み取りを持つことになり、私もjxtableのpackAllを使用してみましたが、それはJTableのように振る舞います - 時々切るテキストをオフにして多くのパディングを残す場合があります。 – trickster77777

+0

列グリッド(like1 extra pixel)を追加したり、追加パディングを追加する必要があります。これがうまくいくためには、固定幅フォントを使用していることを確認してください。 – MadProgrammer

+0

固定幅フォントはどういう意味ですか?私はテーブルを動的に埋めて、次のコンテンツの幅はわかりません。また、私はsetRowHeightを使用する場合、間違った列の幅が頻繁に表示され、どのようにその関連性を理解することはできません。 – trickster77777

答えて

15

あなたの例で多くの問題があります更新

enter image description here

public class TestTable01 extends JPanel { 

    private JTable mainTable; 

    public TestTable01() { 
     super(new GridLayout(1, 0)); 

     String[] columnNames = {"First Name", 
           "Last Name", 
           "Sport", 
           "# of Years", 
           "Vegetarian"}; 

     Object[][] data = { 
      {"Kathy", "Smith", 
      "Snowboarding", new Integer(5), new Boolean(false)}, 
      {"John", "Doe", 
      "Rowing", new Integer(3), new Boolean(true)}, 
      {"Sue", "Black", 
      "Knitting", new Integer(2), new Boolean(false)}, 
      {"Jane", "White", 
      "Speed reading", new Integer(20), new Boolean(true)}, 
      {"Joe", "Brown", 
      "Pool", new Integer(10), new Boolean(false)} 
     }; 

     mainTable = new JTable(data, columnNames); 
     mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 
     mainTable.setPreferredScrollableViewportSize(new Dimension(500, 70)); 
     mainTable.setFillsViewportHeight(true); 

     update(); 

     //Create the scroll pane and add the table to it. 
     JScrollPane scrollPane = new JScrollPane(mainTable); 

     //Add the scroll pane to this panel. 
     add(scrollPane); 
    } 

    /** 
    * Create the GUI and show it. For thread safety, this method should be 
    * invoked from the event-dispatching thread. 
    */ 
    private static void createAndShowGUI() { 
     //Create and set up the window. 
     JFrame frame = new JFrame("SimpleTableDemo"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     //Create and set up the content pane. 
     TestTable01 newContentPane = new TestTable01(); 
     newContentPane.setOpaque(true); //content panes must be opaque 
     frame.setContentPane(newContentPane); 

     //Display the window. 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    private void update() { 
     System.out.println("updating"); 

     adjustJTableRowSizes(mainTable); 
     for (int i = 0; i < mainTable.getColumnCount(); i++) { 
      adjustColumnSizes(mainTable, i, 2); 
     } 
    } 

    private void adjustJTableRowSizes(JTable jTable) { 
     for (int row = 0; row < jTable.getRowCount(); row++) { 
      int maxHeight = 0; 
      for (int column = 0; column < jTable.getColumnCount(); column++) { 
       TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column); 
       Object valueAt = jTable.getValueAt(row, column); 
       Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column); 
       int heightPreferable = tableCellRendererComponent.getPreferredSize().height; 
       maxHeight = Math.max(heightPreferable, maxHeight); 
      } 
      jTable.setRowHeight(row, maxHeight); 
     } 

    } 

    public void adjustColumnSizes(JTable table, int column, int margin) { 
     DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); 
     TableColumn col = colModel.getColumn(column); 
     int width; 

     TableCellRenderer renderer = col.getHeaderRenderer(); 
     if (renderer == null) { 
      renderer = table.getTableHeader().getDefaultRenderer(); 
     } 
     Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0); 
     width = comp.getPreferredSize().width; 

     for (int r = 0; r < table.getRowCount(); r++) { 
      renderer = table.getCellRenderer(r, column); 
      comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, column), false, false, r, column); 
      int currentWidth = comp.getPreferredSize().width; 
      width = Math.max(width, currentWidth); 
     } 

     width += 2 * margin; 

     col.setPreferredWidth(width); 
     col.setWidth(width); 
    } 

    public static void main(String[] args) { 
     //Schedule a job for the event-dispatching thread: 
     //creating and showing this application's GUI. 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowGUI(); 
      } 

     }); 
    } 

} 

...私のために大丈夫動作しているようです。

  • テーブルが本当にJScrollPaneに追加する必要があり、これは、それはあなたが望むものはおそらくありませんが、JPanelため
  • デフォルトのレイアウトマネージャは、この場合には、FlowLayoutです...ヘッダを付加するの世話をしますBorderLayout
  • スイングはスレッドセーフではありません。 java.util.Timerのユーザーがこのポリシーに違反すると、モデルとビューが同期しなくなる可能性があります。代わりにjavax.swing.Timerを使用してください。
  • 2つずつレンダリングすると、htmlレイアウトエンジンは要素間にウィークブレイクを起こします。つまり、エンジンが2つの要素を一緒にレンダリングするのに十分な空き領域がないと判断した場合、エンジンはそれらを分割します。代わりに2つの<span>タグを使用して1つの<div>を使用することをおすすめします。

私は

enter image description here

public class TestColumnWidths { 

    private static JTable mainTable; 
    private static Random random = new Random(); 
    private static List<Data> data; 

    private static class Data { 

     String name; 
     String surname; 

     private Data(String name, String surname) { 
      this.name = name; 
      this.surname = surname; 
     } 
    } 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 

       data = stubProvider(); 

       final JFrame frame = new JFrame("table adjust example"); 
       frame.add(createUI()); 
       frame.pack(); 
       frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 

       update(); 
//     java.util.Timer timer = new java.util.Timer(); 
//     timer.schedule(new TimerTask() { 
//      @Override 
//      public void run() { 
//       update(); 
//      } 
//     }, 3000, 3000); 

       javax.swing.Timer timer = new javax.swing.Timer(3000, new ActionListener() { 
        @Override 
        public void actionPerformed(ActionEvent e) { 
         update(); 
        } 
       }); 
       timer.setRepeats(true); 
       timer.setCoalesce(true); 
       timer.start(); 

      } 
     }); 
    } 

    private static JPanel createUI() { 
     JPanel jPanel = new JPanel(); 
     mainTable = new JTable(2, 3); 
     mainTable.setModel(new AbstractTableModel() { 
      @Override 
      public int getRowCount() { 
       return data.size(); 
      } 

      @Override 
      public int getColumnCount() { 
       return 2; 
      } 

      @Override 
      public Object getValueAt(int rowIndex, int columnIndex) { 
       Data dataItem = data.get(rowIndex); 
       if (columnIndex == 0) { 
        return dataItem.name; 
       } 
       if (columnIndex == 1) { 
        return dataItem.surname; 
       } 
       throw new IllegalStateException(); 
      } 
     }); 
     mainTable.setGridColor(Color.black); 
     mainTable.setShowHorizontalLines(false); 
     mainTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 

     final TableCellRenderer defaultRenderer = mainTable.getTableHeader().getDefaultRenderer(); 
     mainTable.getTableHeader().setDefaultRenderer(new TableCellRenderer() { 
      @Override 
      public Component getTableCellRendererComponent(JTable jTable, Object o, boolean b, boolean b1, int row, int column) { 
       JLabel parent = (JLabel) defaultRenderer.getTableCellRendererComponent(jTable, o, b, b1, row, column); 
       if (column == 0) { 
        parent.setText("name"); 
       } else { 
        parent.setText("surname"); 
       } 
       return parent; 
      } 
     }); 

//   jPanel.add(mainTable.getTableHeader()); 
//   jPanel.add(mainTable); 

     jPanel.setLayout(new BorderLayout()); 
     jPanel.add(new JScrollPane(mainTable)); 

     return jPanel; 
    } 

    private static void update() { 
     System.out.println("updating"); 
     data = stubProvider(); 

     adjustJTableRowSizes(mainTable); 
     for (int i = 0; i < mainTable.getColumnCount(); i++) { 
      adjustColumnSizes(mainTable, i, 2); 
     } 
    } 

    private static void adjustJTableRowSizes(JTable jTable) { 
     for (int row = 0; row < jTable.getRowCount(); row++) { 
      int maxHeight = 0; 
      for (int column = 0; column < jTable.getColumnCount(); column++) { 
       TableCellRenderer cellRenderer = jTable.getCellRenderer(row, column); 
       Object valueAt = jTable.getValueAt(row, column); 
       Component tableCellRendererComponent = cellRenderer.getTableCellRendererComponent(jTable, valueAt, false, false, row, column); 
       int heightPreferable = tableCellRendererComponent.getPreferredSize().height; 
       maxHeight = Math.max(heightPreferable, maxHeight); 
      } 
      jTable.setRowHeight(row, maxHeight); 
     } 

    } 

    public static void adjustColumnSizes(JTable table, int column, int margin) { 
     DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel(); 
     TableColumn col = colModel.getColumn(column); 
     int width; 

     TableCellRenderer renderer = col.getHeaderRenderer(); 
     if (renderer == null) { 
      renderer = table.getTableHeader().getDefaultRenderer(); 
     } 
     Component comp = renderer.getTableCellRendererComponent(
       table, col.getHeaderValue(), false, false, 0, 0); 
     width = comp.getPreferredSize().width; 

     for (int r = 0; r < table.getRowCount(); r++) { 
      renderer = table.getCellRenderer(r, column); 
      comp = renderer.getTableCellRendererComponent(
        table, table.getValueAt(r, column), false, false, r, column); 
      int currentWidth = comp.getPreferredSize().width; 
      width = Math.max(width, currentWidth); 
     } 

     width += 2 * margin; 

     col.setPreferredWidth(width); 
    } 

    private static List<Data> stubProvider() { 
     List<Data> data = new ArrayList<Data>(); 
     for (int i = 0; i < 4; i++) { 
      data.add(new Data(
        "<html>" 
        + "<div>" 
        + "<span style='font-size: 15px'>Jason</span>" 
        + "<span style='font-size: 15px'>" + random.nextInt() + "</span>" 
        + "</div>" 
        + "</html>", 
        "Statham " + random.nextInt())); 
     } 
     return data; 
    } 
} 
+0

あなたの例では、タイマーとスクリーンショットで更新メソッドをラップしていますが、2番目の列に不適切なサイズがあることがわかりますhttp://i45.tinypic.com/359eooj.png ( – trickster77777

+0

?タイマーのタイプは?私は遊ぶことができるサンプルコードを持っていますか? – MadProgrammer

+0

私の例で使用したのと同じです – trickster77777

0

あまりに狭い列の合理的な最小幅を設定します。列の内容に応じて幅を計算して設定します。

+0

問題は、いくつかの条件で 'Component'(セルの内容)が間違ったPreferredSizeを返すことです。そのため、MinSizeまたはPrefSizeを設定しても問題ありません。私はすべてのテーブルの更新後に列を調整する必要があります。 – trickster77777

+3

@ trickster77777 1)文字列値からmaxSizeを取得し、この値をColumnModelの最後の列に適用する問題はありません。2)いくつかの条件で誤ったPreferredSizeを返します.-短期間で実行可能でコンパイル可能なSSCCE ](http://sscce.org/) – mKorbel

関連する問題