CellContext.isExpanded() всегда возвращает true в JXTreeTable
Я использую 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
определить, расширен ли ряд ячейки или нет?
2 ответа
Решение может быть реализовано на основе ответа 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();
}
}
Anyhow the
CellContext
used by theComponentProvider
always indicates that the node is expanded.
This behavior goes back to the implementation of getTableCellRenderer(...) provided by DefaultTableRenderer
: both 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;
}
...
}
It makes sense given those properties are significant in a tree cell context, not a table cell context. Если вы установите TreeCellRenderer
к JXTreeTable
using the very same ComponentProvider
then it should work as expected in the first column (tree column):
ComponentProvider<?> textProvider = new LabelProvider(valueProvider, JLabel.TRAILING) {...};
...
DefaultTreeRenderer treeRenderer = new DefaultTreeRenderer(textProvider);
...
treeTable.setTreeCellRenderer(treeRenderer);
Поскольку CellContext
won't be a TableCellContext
но TreeCellContext
and it will contain the correct 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;
}
...
}