TableColumnExt不尊重原型值

时间:2012-07-13 18:14:37

标签: java swing swingx jxtreetable

我正在尝试使用SwingX的TableColumnExt类为JXTreeTable的分层列中的列宽设置原型值。在我初始化模型和表格后,我这样做:

TableColumnExt column = dataTable.getColumnExt(0);            
column.setPrototypeValue(500);

渲染我的表时,所有列的大小都相同。这些是我在JXTreeTable实例上使用的方法。

dataTable.setRowHeight(28);
dataTable.setFillsViewportHeight(true);
dataTable.setHorizontalScrollEnabled(true);

我在这里做错了什么?

1 个答案:

答案 0 :(得分:2)

正如我在评论中已经提到的,it's a bug。问题很多:

  • 负责测量原型大小要求的代码是ColumnFactory.calcPrototypeWidth
  • 这样做是通过将呈现器配置为具有给定原型的表返回并测量其prefSize
  • 来实现的。
  • 使用黑魔法
  • 将分层列的渲染委托给JTree
  • 默认工厂不知道那个黑魔法,因此查询JTree的prefSize,它独立于原型
  • 第一个想法:让工厂了解分层列的特殊渲染并向下走到真实的底层treeCellRenderer - 再次由于其他内部黑魔法而无法使用
  • 由于设置原型而导致的自动列重新调整大小在JXTable中被破坏(Issue #1510

解决方法涉及

  • 自定义ColumnFactory,它知道分层列的特殊渲染器(== JXTree))
  • 对于分层列,配置并测量TreeCellRenderer - 不是树本身使用的那个,而是一个不相关的虚拟
  • 设置原型后,手动触发列的大小评估

下面是一个自定义的ColumnFactory及其用法(未经过正式测试,所以请耐心等待:-)。

// a custom factory
ColumnFactory factory = new ColumnFactory() {

    @Override
    protected int calcPrototypeWidth(JXTable table,
            TableColumnExt columnExt) {
        if (isHierarchicalPrototype(table, columnExt))  {
            return calcHierarchicalPrototypeWidth((JXTreeTable) table, columnExt);
        }
        return super.calcPrototypeWidth(table, columnExt);
    }

    protected boolean isHierarchicalPrototype(JXTable table,
            TableColumnExt columnExt) {
        return (table instanceof JXTreeTable) 
                && ((JXTreeTable) table).getTreeTableModel().getHierarchicalColumn() == 
                         columnExt.getModelIndex()
                && columnExt.getPrototypeValue() != null;
    }

    TreeCellRenderer dummy = new DefaultTreeCellRenderer();
    protected int calcHierarchicalPrototypeWidth(JXTreeTable table,
            TableColumnExt columnExt) {
        JXTree renderer = (JXTree) getCellRenderer(table, columnExt);
        // commented lines would be the obvious step down into the "real" sizing
        // requirements, but giving reasonable result due to internal black magic
        // TreeCellRenderer treeRenderer = renderer.getCellRenderer();
        // Component comp = treeRenderer.getTreeCellRendererComponent(renderer, 
              columnExt.getPrototypeValue(), false, false, false, -1, false);
        // instead, measure a dummy
        Component comp = dummy.getTreeCellRendererComponent(renderer, 
                columnExt.getPrototypeValue(), false, false, false, -1, false);

        return Math.max(renderer.getPreferredSize().width, comp.getPreferredSize().width);
    }

};

// usage: first create the treeTable, set the factory and set the model
JXTreeTable table = new JXTreeTable();
table.setColumnFactory(factory);
table.setTreeTableModel(new FileSystemModel());
// set the prototype
table.getColumnExt(0).setPrototypeValue("long longer longest still not enough to really see" +
           " some effect of the prototype if available");
// Issue #1510: prototype value handling broken in underlying JXTable
// need to manually force the config
table.getColumnFactory().configureColumnWidths(table, table.getColumnExt(0));