2014-12-11 3 views
1

Я использую JXTreeTable. Я хочу показать текст в ячейке, только если строка свернута. Если строка расширяется, подробные значения отображаются в дочерних элементах, поэтому сокращенный текст в родительском объекте больше не должен быть видимым.CellContext.isExpanded() всегда возвращает true в JXTreeTable

Насколько я знаю, это необходимо реализовать, предоставив специальный ComponentProvider, используемый DefaultTableRenderer. Во всяком случае CellContext, используемый ComponentProvider, всегда указывает, что узел расширен. context.isExpanded() всегда возвращает true.

StringValue valueProvider = new StringValue() 
{ 
    @Override 
    public String getString(Object value) 
    { 
     return String.valueOf(value); 
    } 
}; 
ComponentProvider<?> textProvider = new LabelProvider(valueProvider, JLabel.TRAILING) 
{ 
    @Override 
    protected String getValueAsString(CellContext context) 
    { 
     System.out.println("Context expanded " + context.isExpanded()); 
     if (context.isExpanded()) 
     { 
      return ""; 
     } 
     return super.getValueAsString(context); 
    } 
}; 
DefaultTableRenderer renderer = new DefaultTableRenderer(textProvider); 

Что я должен изменить в ComponentProvider обнаружить, если строка клетки расширяется или нет?

ответ

1

решения может быть реализовано на основе ответа dic19.

Решение заключается в реализации специального средства визуализации с использованием метода getTableCellRendererComponent, который проверяет наличие JXTreeTable. В таком случае он вычисляется, если строка расширяется. Также может быть добавлена ​​проверка флага leaf.

К сожалению, невозможно изменить DefaultTableRenderer, потому что CellContext не отображается в классах переопределения.

public class DefaultTreeTableRenderer 
    extends AbstractRenderer 
    implements TableCellRenderer 
{ 

    private TableCellContext cellContext; 

    /** 
    * Instantiates a default table renderer with the default component provider. 
    * 
    * @see #DefaultTableRenderer(ComponentProvider) 
    */ 
    public DefaultTreeTableRenderer() 
    { 
     this((ComponentProvider<?>)null); 
    } 

    /** 
    * Instantiates a default table renderer with the given component provider. If the controller is null, creates 
    * and uses a default. The default provider is of type <code>LabelProvider</code>. 
    * 
    * @param componentProvider the provider of the configured component to use for cell rendering 
    */ 
    public DefaultTreeTableRenderer(ComponentProvider<?> componentProvider) 
    { 
     super(componentProvider); 
     this.cellContext = new TableCellContext(); 
    } 

    /** 
    * Instantiates a default table renderer with a default component provider using the given converter. 
    * 
    * @param converter the converter to use for mapping the content value to a String representation. 
    * @see #DefaultTableRenderer(ComponentProvider) 
    */ 
    public DefaultTreeTableRenderer(StringValue converter) 
    { 
     this(new LabelProvider(converter)); 
    } 

    /** 
    * Instantiates a default table renderer with a default component provider using the given converter and 
    * horizontal alignment. 
    * 
    * @param converter the converter to use for mapping the content value to a String representation. 
    * @see #DefaultTableRenderer(ComponentProvider) 
    */ 
    public DefaultTreeTableRenderer(StringValue converter, int alignment) 
    { 
     this(new LabelProvider(converter, alignment)); 
    } 

    /** 
    * Intantiates a default table renderer with default component provider using both converters. 
    * 
    * @param stringValue the converter to use for the string representation 
    * @param iconValue the converter to use for the icon representation 
    */ 
    public DefaultTreeTableRenderer(StringValue stringValue, IconValue iconValue) 
    { 
     this(new MappedValue(stringValue, iconValue)); 
    } 

    /** 
    * Intantiates a default table renderer with default component provider using both converters and the given 
    * alignment. 
    * 
    * @param stringValue the converter to use for the string representation 
    * @param iconValue the converter to use for the icon representation 
    * @param alignment the rendering component's horizontal alignment 
    */ 
    public DefaultTreeTableRenderer(StringValue stringValue, IconValue iconValue, int alignment) 
    { 
     this(new MappedValue(stringValue, iconValue), alignment); 
    } 

    // -------------- implements javax.swing.table.TableCellRenderer 
    /** 
    * Returns a configured component, appropriate to render the given list cell. 
    * <p> 
    * Note: The component's name is set to "Table.cellRenderer" for the sake of Synth-based LAFs. 
    * 
    * @param table the <code>JTable</code> 
    * @param value the value to assign to the cell at <code>[row, column]</code> 
    * @param isSelected true if cell is selected 
    * @param hasFocus true if cell has focus 
    * @param row the row of the cell to render 
    * @param column the column of the cell to render 
    * @return the default table cell renderer 
    */ 
    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, 
     boolean hasFocus, int row, int column) 
    { 
     boolean expanded = true; 
     boolean leaf = true; 
     if (table instanceof JXTreeTable) 
     { 
      JXTreeTable treeTable = (JXTreeTable)table; 
      expanded = treeTable.isExpanded(row); 
     } 
     this.cellContext.installContext(table, value, row, column, isSelected, hasFocus, expanded, leaf); 
     Component comp = this.componentController.getRendererComponent(this.cellContext); 
     // fix issue #1040-swingx: memory leak if value not released 
     this.cellContext.replaceValue(null); 
     return comp; 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    @Override 
    protected ComponentProvider<?> createDefaultComponentProvider() 
    { 
     return new LabelProvider(); 
    } 

} 
0

CellContext Так или иначе используется ComponentProvider всегда указывает на то, что узел расширяется.

Такое поведение восходит к реализации getTableCellRenderer(...) предоставленной DefaultTableRenderer: оба expanded и leaf свойство установлено в true:

public class DefaultTableRenderer extends AbstractRenderer implements TableCellRenderer { 

    private TableCellContext cellContext; 

    ... 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 

     // both 'expanded' and 'leaf' properties are set to 'true' here: 
     cellContext.installContext(table, value, row, column, isSelected, hasFocus, true, true); 
     // 'componentController' is an instance of 'ComponentProvider<?>' 
     Component comp = componentController.getRendererComponent(cellContext); 
     cellContext.replaceValue(null); 
     return comp; 
    } 

    ... 
} 

Это имеет смысл, учитывая эти свойства имеют важное значение в контексте дерева клеток , а не контекст ячейки. Если вы установите TreeCellRenderer в JXTreeTable, используя тот же самый ComponentProvider то он должен работать, как ожидается, в первом столбце (дерево колонка):

ComponentProvider<?> textProvider = new LabelProvider(valueProvider, JLabel.TRAILING) {...}; 
... 
DefaultTreeRenderer treeRenderer = new DefaultTreeRenderer(textProvider); 
... 
treeTable.setTreeCellRenderer(treeRenderer); 

Поскольку CellContext не будет TableCellContext но TreeCellContext и это будет содержит правильное expanded и leaf значения:

public class DefaultTreeRenderer extends AbstractRenderer implements TreeCellRenderer { 

    private TreeCellContext cellContext; 

    ... 

    @Override 
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { 

     // both 'expanded' and 'leaf' properties are correctly set here: 
     cellContext.installContext(tree, value, row, 0, selected, hasFocus, expanded, leaf); 
     // 'componentController' is an instance of 'ComponentProvider<?>' 
     Component comp = componentController.getRendererComponent(cellContext); 
     cellContext.replaceValue(null); 
     return comp; 
    } 

    ... 
} 
+0

Это приводит к решению, указанному в моем редактируемом вопросе. Благодаря! – Uli

+1

Я рад, что это помогло! Пожалуйста, подумайте о том, чтобы добавить свое редактирование в качестве ответа и принять его вместо моего, поскольку вопрос должен содержать только проблему. Я бы сказал это наверняка :) Если бы этот ответ был полезен, вы можете его проголосовать. @Uli – dic19