Resize JTable以适应内容不能精确地工作,从而导致省略



我想根据列标题标签或包含同一列最长字符串的行(以最大的为准)完美地调整JTable的大小,以适合其模型内容。我不想使用渲染器来决定这些大小,因为我想根据文本值动态地节省尽可能多的屏幕空间。

现在,如果用户将帧的大小调整为大于表的内容,那么额外的空间将留给最后一列。

这是一个非常特殊的表,不应该被重新排序。也不允许调整标题列的大小

我拥有的代码(几乎)完成了所有这些。出于某种原因,该表显示了……(省略)在每一列的末尾,即使我知道FontMetrics建议我有正确的文本长度,以完全适合。

这是Java Swing的bug吗?如何以优雅的方式解决这个问题?

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class Scrollable_Table_Example extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel _panel;
private JTextArea _text;
private JTable _table;
private DefaultTableModel _model;
private JScrollPane _scroll;
public static void main(String[] args) {
Scrollable_Table_Example app = new Scrollable_Table_Example();
app.setVisible(true);
}   
public Scrollable_Table_Example() {
_panel = new JPanel(new BorderLayout());
setPreferredSize(new Dimension(300, 500));

_text = new JTextArea(300, 300);
_text.setEditable(false);
JScrollPane areaScrollPane = new JScrollPane(_text);
areaScrollPane.setPreferredSize(new Dimension(250, 250));
areaScrollPane.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
areaScrollPane.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
areaScrollPane.add(_text);
_panel.add(areaScrollPane, BorderLayout.NORTH);
_model = new DefaultTableModel();
_model.addColumn("Type");
_model.addColumn("Schema");
_model.addColumn("Module Name");
_model.addColumn("Path");
_table = new JTable();
_table.setAutoResizeMode( JTable.AUTO_RESIZE_OFF );
_table.getTableHeader().setResizingAllowed(false);
_table.getTableHeader().setReorderingAllowed(false);
_table.setModel(_model);
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
resizeColumnWidth(_table);
}
});

for(int i = 0; i < 20; i++) {
Vector<String> r  = new Vector<String>();
r.addElement("TABLE");
r.addElement("dbo");
r.addElement("Policy");
r.addElement("OBJECTS -> INSURANCE -> Policy");
_model.addRow(r);
}
_scroll = new JScrollPane(_table);
_panel.add(_scroll, BorderLayout.CENTER);
add(_panel);
pack();
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
}   
public static void resizeColumnWidth(JTable table) {
final TableColumnModel columnModel = table.getColumnModel();
FontMetrics fontMetrics = table.getFontMetrics(table.getFont());
for (int column = 0; column < table.getColumnCount(); column++) {
String headerValue = columnModel.getColumn(column).getHeaderValue().toString();
int headerWidth = fontMetrics.stringWidth(headerValue);
int width = headerWidth;
for (int row = 0; row < table.getRowCount(); row++) {
String columnValue = table.getModel().getValueAt(row, column).toString();
int columnValueWidth = fontMetrics.stringWidth(columnValue);
width = Math.max(width, Math.max(headerWidth, columnValueWidth));
}
columnModel.getColumn(column).setPreferredWidth(width);
}
int parentWidth = table.getParent().getSize().width;
int tableWidth = table.getPreferredSize().width;

if(parentWidth > tableWidth) {
int diff = parentWidth - tableWidth;
int newWidth = columnModel.getColumn(3).getPreferredWidth() + diff;
columnModel.getColumn(3).setPreferredWidth(newWidth);
}
}
}

我能做的最好的就是从TableModel中取出margin并乘以3。感谢MadProgrammer和Gilbert的指导。这似乎是完美的像素…

public static final void resizeColumnWidth(JTable table) {
final TableColumnModel columnModel = table.getColumnModel();
int margin = columnModel.getColumnMargin() * 3;


System.out.println(margin);

FontMetrics fontMetrics = table.getFontMetrics(table.getFont());
for (int column = 0; column < table.getColumnCount(); column++) {
String headerValue = columnModel.getColumn(column).getHeaderValue().toString();
int headerWidth = fontMetrics.stringWidth(headerValue) + margin;
int width = headerWidth;
for (int row = 0; row < table.getRowCount(); row++) {
String columnValue = table.getModel().getValueAt(row, column).toString();
int columnValueWidth = fontMetrics.stringWidth(columnValue) + margin;
width = Math.max(width, Math.max(headerWidth, columnValueWidth));
}
columnModel.getColumn(column).setPreferredWidth(width);
}
int parentWidth = table.getParent().getSize().width;
int tableWidth = table.getPreferredSize().width;

if(parentWidth > tableWidth) {
int diff = parentWidth - tableWidth;
int newWidth = columnModel.getColumn(3).getPreferredWidth() + diff;
columnModel.getColumn(3).setPreferredWidth(newWidth);
}           
}

最新更新