我试图设置一个多列SWT Tree
(通过JFace TreeViewer
),允许其列通过拖动列标题由用户重新排序。然而,第一列应该保持固定和不可移动。除了第一个,我可以对每个TreeColumn
使用setMoveable(true)
方法来获得真正的接近,但这并不能阻止用户将不同的列拖到它的左边。有什么办法解决这个问题吗?
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
public class TreeTableColumnMove {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new RowLayout(SWT.HORIZONTAL));
Tree tree = new Tree(shell, SWT.BORDER | SWT.CHECK);
tree.setLayoutData(new RowData(-1, 100));
tree.setHeaderVisible(true);
for (int i = 0; i < 5; i++) {
TreeColumn column = new TreeColumn(tree, SWT.CENTER);
column.setText("Col " + i);
column.setWidth(60);
if (i > 0) column.setMoveable(true);
}
TreeItem item = new TreeItem(tree, SWT.NONE);
item.setText(new String[] { "c0", "c1", "c2", "c3", "c4" });
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
根据danmec的回答,我的最终解决方案是:
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
public class TreeTableColumnMove {
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new RowLayout(SWT.HORIZONTAL));
final Tree tree = new Tree(shell, SWT.BORDER | SWT.CHECK);
tree.setLayoutData(new RowData(-1, 100));
tree.setHeaderVisible(true);
Listener moveListener = new Listener() {
public void handleEvent(Event e) {
int[] order = tree.getColumnOrder();
for(int i=0, col=0; i<order.length; i++) {
int tmp = order[i];
order[i] = col;
col = tmp;
if(col == 0)
if(i == 0) return;
else break;
}
tree.setColumnOrder(order);
}
};
for (int i = 0; i < 5; i++) {
TreeColumn column = new TreeColumn(tree, SWT.CENTER);
column.setText("Col " + i);
column.setWidth(60);
if (i == 0)
column.addListener(SWT.Move, moveListener);
else
column.setMoveable(true);
}
TreeItem item = new TreeItem(tree, SWT.NONE);
item.setText(new String[] { "c0", "c1", "c2", "c3", "c4" });
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}
我不知道是否有可能阻止它,但是你可以处理列移动的结果,并对它做出反应以实现你想要的。
也许这是一个很好的起点?从本质上讲,它侦听被移动的第一列(不是直接的,而是由于另一列被移动到它的左边而被移动),然后重新洗刷顺序,使它在视觉上再次成为第一列。
注意,不管视觉顺序如何,创建的第一列总是0(以此类推)。方法tree.getColumnOrder()将以可视化方式排序,其值是创建的顺序索引(因此,如果交换第二列和第三列,该方法将返回[0,2,1,3,4])
for (int i = 0; i < 5; i++) {
TreeColumn column = new TreeColumn(tree, SWT.CENTER);
column.setText("Col " + i);
column.setWidth(60);
if (i > 0) column.setMoveable(true);
// NEW CODE HERE
if (i == 0) {
column.addControlListener(new ControlAdapter() {
public void controlMoved(ControlEvent e) {
List<Integer> newOrder = new ArrayList<Integer>();
// add the first
newOrder.add(0);
// loop around all columns
for (int col : tree.getColumnOrder()) {
// if not the first that was added, add to list
if (col != 0) {
newOrder.add(col);
}
}
// convert list to array
int[] newOrderArray = new int[newOrder.size()];
for (int j = 0; j < newOrder.size(); j++) {
newOrderArray[j] = newOrder.get(j);
}
// update tree order
tree.setColumnOrder(newOrderArray);
}
});
}
}