我正在使用答案 https://stackoverflow.com/a/5820366和 http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/它有效,但列的大小经常太宽或太窄。
无论用 HTML 还是文本填充我的表格。
使用标准 TableModel
来自 oracle 文档。
调整模式 = JTable.AUTO_RESIZE_OFF
我的 tabel 容器是 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 示例:
"<html><pre><font size=+1 face='Arial'>" + firstValue + "\n" + secondValue + "</font></pre></html>"
简单行:
firstValue + " - " + secondValue
例子如下:
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;
}
}
我在调整行高时遇到了这样的问题。使用 <pre>\n</pre>
而不是 <br>
固定行调整。
最佳答案
对我来说似乎工作正常......
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
, 这将负责添加 header ... JPanel
的默认布局管理器是FlowLayout
,在这种情况下,它可能不是你想要的,你可能想使用BorderLayout
- Swing 不是线程安全的。
java.util.Timer
的用户将违反此政策,这可能会导致模型和 View 不同步。使用javax.swing.Timer
相反。 - 渲染两个
<div>
每一个旁边都会导致 html 布局引擎在元素之间放置一个弱分隔符。也就是说,如果引擎认为没有足够的可用空间来同时渲染这两个元素,它会将它们分开。最好使用单个<div>
有两个<span>
标签代替...
我想读一读
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;
}
}
关于java - 如何调整 JTable 列以适应列单元格中最长的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13013989/