2012-10-22 26 views
11

Ich benutze Antwort https://stackoverflow.com/a/5820366 und http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/ und es funktioniert, aber häufig Spalten Größen sind zu breit oder zu schmal.Wie JTable Spalten anpassen, um den längsten Inhalt in Spalte Zellen passen

Egal, meine Tabelle mit HTML oder Text zu füllen.

Verwendung von Standard TableModel von Oracle-Dokumentation.

Resize mode = JTable.AUTO_RESIZE_OFF

Container meiner tabel ist JGoodies:

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 Beispiel:

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

einfache Reihe:

firstValue + " - " + secondValue 

Hier t er Beispiel:

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; 
} 
} 

I solches Problem mit Reihenhöhenverstellung aufweisen. Verwendung von <pre>\n</pre> anstelle von <br> feste Zeileneinstellung.

+0

Ich habe auch versucht packAll von jxtable verwenden, aber es verhält sich wie jtable - manchmal schneidet Aus dem Text und manchmal lässt viel Padding – trickster77777

+0

Sie müssen möglicherweise in der Spalte Raster hinzufügen (like1 extra Pixel) und/oder fügen Sie in einigen zusätzlichen Padding. Damit dies funktioniert, stellen Sie sicher, dass Sie eine Schriftart mit fester Breite verwenden. – MadProgrammer

+0

was meinst du feste Breite Schriftart? Ich fülle die Tabelle dynamisch und ich kenne die Breite des nächsten Inhalts nicht. Auch wenn ich setRowHeight benutze, erscheint die falsche Spaltenbreite häufiger und ich kann nicht verstehen, wie es zusammenhängt. – trickster77777

Antwort

15

scheint in Ordnung für mich zu arbeiten ...

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(); 
      } 

     }); 
    } 

} 

AKTUALISIERT

Es gibt eine Reihe von Problemen mit Ihrem Beispiel.

  • Tabellen wirklich zu einem JScrollPane hinzugefügt werden sollen, wird dies den Header der Zugabe ...
  • Der Standard-Layout-Manager für ein JPanel ist FlowLayout, in diesem Fall darauf achten, es ist wahrscheinlich nicht das, was Sie wollen, Sie möchten wahrscheinlich ein BorderLayout verwenden
  • Swing ist nicht Thread sicher. Der Benutzer von java.util.Timer verletzt diese Richtlinie. Dies könnte dazu führen, dass das Modell und die Ansicht nicht mehr synchron sind. Verwenden Sie stattdessen eine javax.swing.Timer.
  • Rendern zwei <div> neben jedem wird die HTML-Layout-Engine eine schwache Pause zwischen den Elementen platzieren. Das heißt, wenn die Engine entscheidet, dass nicht genug Platz zur Verfügung steht, um die beiden Elemente zusammen zu rendern, werden sie geteilt. Besser, eine einzelne <div> mit zwei <span> Tags stattdessen zu verwenden ...

Ich hätte eine Lese von

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

In Ihrem Beispiel habe ich Update-Methode in Timer eingewickelt und auf Screenshot können Sie sehen, dass die zweite Spalte unpassende Größe hat http://i45.tinypic.com/359eooj.png Wie kann ich Überwindung dieser bösartigen Tabelle :( – trickster77777

+0

? Welche Art von Timer? Haben Sie Beispielcode mit dem ich spielen kann? – MadProgrammer

+0

das gleiche ich in meinem Beispiel – trickster77777

0

Setzen Sie eine angemessene Mindestbreite für die Spalten, die zu schmal sind. Dann berechne die Breite entsprechend dem Inhalt der Spalten und setze sie.

+0

Das Problem ist, dass 'Component' (Inhalt der Zelle) falsche PreferredSize unter bestimmten Bedingungen zurückgibt. Deshalb legen Sie MinSize oder PreFSize fest. Ich muss Spalten nach jedem Tabellenupdate anpassen. – trickster77777

+3

@ trickster77777 1) gibt es kein Problem, maxSize von String-Wert zu erhalten und diesen Wert auf die letzte Spalte im ColumnModel, 2) 'gibt falsche PreferredSize in einigen Bedingungen zurück" - für bessere Hilfe eher eine kurze, runnable und kompilierbar [SSCCE ] (http://sscce.org/) – mKorbel