设置 JTable 列的原型值(用于自动宽度计算)

Posted

技术标签:

【中文标题】设置 JTable 列的原型值(用于自动宽度计算)【英文标题】:setting a prototype value (for auto-width calculation) of a JTable column 【发布时间】:2010-10-24 16:44:52 【问题描述】:

要么这不存在,要么我没有正确思考/搜索,因为它已经晚了......

我想根据我期望(或知道)存在于特定列中的最大字符串的原型值在 Swing 中设置 JTable 列宽。我不知道像素数,因为我在编译时不一定知道字体。

有没有办法为列宽和行高设置原型值?如果有,怎么做?

【问题讨论】:

【参考方案1】:

你可以试试下面的代码:

/**
 * Sets the preferred width of the columns of a table from prototypes
 * @param table the target table
 * @param prototypes an array of prototypes, @code null values will be ignored
 * @param setMaxWidth @code true if the maximum column width should also be set
 */
public static void setWidthFromPrototype(JTable table, Object[] prototypes, boolean setMaxWidth) 
if (prototypes.length != table.getColumnCount())
  throw new IllegalArgumentException("The prototypes array should contain exactly one element per table column");
for (int i = 0; i < prototypes.length; i++) 
    if (prototypes[i] != null) 
        Component proto = table.getCellRenderer(0,i)
                .getTableCellRendererComponent(table, prototypes[i], false, false, 0, i);
        int prefWidth = (int) proto.getPreferredSize().getWidth() + 1;
        table.getColumnModel().getColumn(i).setPreferredWidth(prefWidth);
        if (setMaxWidth)
            table.getColumnModel().getColumn(i).setMaxWidth(prefWidth);
    


【讨论】:

要使用它,只需调用 setWidthFromPrototype(myTable, new Object[]"Not Applicable"); 赞成测量渲染器提供的组件 - 只是获取渲染器是错误的:您必须向表格询问它(table.getRenderer(row,column)),否则,您会错过每列渲染器 - 请编辑完美:-) 感谢@kleopatra 的建议,但我没有看到JTable.getRenderer(int,int) 方法。在所有情况下,我认为getDefaultRenderer 更安全,因为它返回与类型关联的渲染器,如果您不想创建对象的完整实例,例如只传递其字符串表示形式,这可能很有用。跨度> 不,您认为 getDefaultRenderer 更安全 是错误的:由表决定使用哪个渲染器在 getCellRenderer 中发生(确实,您找到了正确的方法名称 :-) 不过,您评论的最后一部分没有多大意义:渲染器查找机制并不关心您的数据如何存储在模型中... 请允许我澄清一下:假设您有一个班级 Student 存储姓名、ID、完整的成绩历史记录。您可以定义一个自定义渲染器,它将以“Name Surname GPA”的形式渲染 Student 的实例。如果您只是对设置列宽感兴趣,您可能不想(或不能)创建一个完整的 Student 实例,而只是将“John Doe 4.5”作为原型传递,在这种情况下使用 @987654324 提供的渲染@ 可能会导致转换异常。【参考方案2】:

您是否尝试过在运行时创建 JLabel 并使用其大小来调整表格的大小?

// create a label that will be using the run-time font
JLabel prototypeLabel = new JLabel("Not Applicable")

// get the labels preferred sizes
int preferredWidth = prototypeLabel.getPreferredSize().getWidth();
int preferredHeight = prototypeLabel.getPreferredSize().getHeight();

// set the sizes of the table's row and columns
myTable.setRowHeight(preferredHeight);

for(TableColumn column : myTable.getColumnModel.getColumns())
   column.setPreferredWidth(preferredWidth);        

【讨论】:

哦,这很聪明。有什么方法可以确保 JLabel 和表格列条目使用相同的字体? 这可能取决于您的 TableCellRenderer 使用的字体。如果您可以访问渲染器,并且它们也是 JLabel 的,您可以使用相同的字体创建原型标签,例如: JLabel prototypeLabel = new JLabel("Not Applicable"); prototypeLabel.setFont(cellRenderer.getFont()) -1 使用任意组件来测量尺寸不是一个好主意。而是使用表格提供的渲染组件【参考方案3】:

SwingX扩展的 JXTable/Column 支持为初始列宽大小设置原型,您可以在创建列之后这样做

for(int col = 0; ....) 
    table.getColumnExt(col).setPrototypeValue(myPrototype[col]

或者通过实现一个自定义的 ColumnFactory 来配置创建时的列

ColumnFactory factory = new ColumnFactory() 
    @Override
    protected void configureTableColumn(TableModel model, TableColumnExt columnExt) 
        super(...);
        columnExt.setPrototypeValue(myPrototype[columnExt.getModelIndex()];
    

table.setColumnFactory(factory);
table.setModel(myModel);

【讨论】:

【参考方案4】:

不创建标签,而是从 TableCellRenderer 获取实际组件并测试其大小:

// create the component that will be used to render the cell
Comp prototype = table.getDefaultRenderer(model.getColumnClass(i)).getTableCellRendererComponent(table, "Not Applicable", false, false, 0, i);

// get the labels preferred sizes
int preferredWidth = comp.getPreferredSize().getWidth();
int preferredHeight = comp.getPreferredSize().getHeight();

这是一个单列示例,您需要重复此操作以获取每列的大小(并设置它)。有关此示例,请参阅 http://www.exampledepot.com/egs/javax.swing.table/PackCol.html

【讨论】:

???这如何反映特定最大长度字符串的宽度/高度?我希望可以包含“$222.22”的列的宽度小于可以包含“杂货购买”的列的宽度。 这是一个单列示例,您需要重复此操作以获取每列的大小(并设置它)。有关此示例,请参阅 exampledepot.com/egs/javax.swing.table/PackCol.html。 JLabel 答案将有同样的问题,因为您将每一列设置为相同的首选宽度。【参考方案5】:

如果您在编译时不知道字体,那么任何 JTable 列的宽度总是未知的。作为完整性检查,打开一个文本文档并使用不同的字体,同时保持点大小不变。所写内容的长度因字体而异,但高度不会。

JTable 行的高度应该能够针对任何字体大小(以磅为单位)确定,因为它是defined standard。不过,这可能需要一些试验,因为 JTable 可能会在单元格之间提供一些间距。

如果您在编译时既不能保证字体大小也不能保证字体本身,那么我对其他人提出的答案很感兴趣:)

【讨论】:

"任何 JTable 列的宽度总是未知的。" ???我有一些示例文本,例如我想用作最大列宽的“不适用”。当然在运行时,当字体已知时,可以从中确定列宽吗?

以上是关于设置 JTable 列的原型值(用于自动宽度计算)的主要内容,如果未能解决你的问题,请参考以下文章

自动计算 JTable 中的列宽

JTable自动读取空值问题

jqGrid属性介绍

如何使 JTable 自动调整大小和水平滚动?

如何更改JTable中列的名称

如何设置winform中gridview的表头宽度,及编号