In a tree with multiple columns, how do I resize columns to contents upon expand/collapse and data updates?
The solution to the similar question for tables doesn't work.
Same as:
tree.addListener(SWT.Collapse, new Listener(){
@Override
public void handleEvent(Event e) {
expandAndResize(false, (TreeItem) e.item);
}
});
tree.addListener(SWT.Expand, new Listener() {
@Override
public void handleEvent(Event event) {
expandAndResize(false, (TreeItem) event.item);
}
});
private static void expandAndResize(Boolean expand_, TreeItem item_)
{
System.out.println( (expand_?"Expanding":"Collapsing") + "item={" + item_ + "}");
item_.setExpanded(expand_);
System.out.println(" Resizing columns");
resizeTree(item_.getParent());
}
private static void resizeTree(Tree tree_)
{
for (TreeColumn tc: tree_.getColumns())
resizeTreeColumn(tc);
}
private static void resizeTreeColumn(TreeColumn treeColumn_)
{
treeColumn_.pack();
}
This works for data updates (by calling the resizeTree
), but for expands/collapses it is one step behind!
More specifically, if I expand an item in the first column, and the underlying item is longer than the column width, the resize to that width will be done upon a next collapse or expand of some other item (or if I directly call resizeTree
).
Just in case it is important: the data is given by TreeContentProvider
and ITableLabelProvider
, and my guess is that ITableLabelProvider
might cause the problem (the width of the column is adjusted before the l开发者_C百科abel gets generated?!)
X-posted to Eclipse Community Forum
A snippet showing your issue would have made this easier.
All you have to do to fix this, is put your listener's code into an asyncExec block, to postpone its execution. (I have a deja-vu, since I answered another question with the same tip very recently...)
BTW: You don't have to call TreeItem.setExpanded(.). Also, don't use Boolean when you have a primitive type. It works, but the VM does auto boxing all the time, which isn't good for performance. That doesn't matter here, but it's a bad habbit. And then: Underscore suffixes for variables?
Now the working snippet, taken and adapted from here:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.*;
public class Snippet {
public static void main( String[] args ) {
final Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
final Tree tree = new Tree(shell, SWT.BORDER);
tree.setHeaderVisible(true);
TreeColumn col1 = new TreeColumn(tree, 0);
col1.setText("col1");
TreeColumn col2 = new TreeColumn(tree, 0);
col2.setText("col2");
for ( int i = 0; i < 4; i++ ) {
TreeItem iItem = new TreeItem(tree, 0);
iItem.setText(new String[] { "TreeItem (0) -" + i, "x" });
for ( int j = 0; j < 4; j++ ) {
TreeItem jItem = new TreeItem(iItem, 0);
jItem.setText(new String[] { "TreeItem (1) -" + i, "x" });
for ( int k = 0; k < 4; k++ ) {
TreeItem kItem = new TreeItem(jItem, 0);
kItem.setText(new String[] { "TreeItem (2) -" + i, "x" });
for ( int l = 0; l < 4; l++ ) {
TreeItem lItem = new TreeItem(kItem, 0);
lItem.setText(new String[] { "TreeItem (3) -" + i, "x" });
}
}
}
}
col1.pack();
col2.pack();
Listener listener = new Listener() {
@Override
public void handleEvent( Event e ) {
final TreeItem treeItem = (TreeItem)e.item;
display.asyncExec(new Runnable() {
@Override
public void run() {
for ( TreeColumn tc : treeItem.getParent().getColumns() )
tc.pack();
}
});
}
};
tree.addListener(SWT.Collapse, listener);
tree.addListener(SWT.Expand, listener);
shell.setSize(200, 200);
shell.open();
while ( !shell.isDisposed() ) {
if ( !display.readAndDispatch() ) display.sleep();
}
display.dispose();
}
}
精彩评论