SWT/JFace树列重新排序- setMoveable()的问题



我试图设置一个多列SWT Tree(通过JFace TreeViewer),允许其列通过拖动列标题由用户重新排序。然而,第一列应该保持固定和不可移动。除了第一个,我可以对每个TreeColumn使用setMoveable(true)方法来获得真正的接近,但这并不能阻止用户将不同的列拖到它的左边。有什么办法解决这个问题吗?

下面是一个简化的工作代码片段(没有JFace)来说明这个问题:
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);
            }
        });
    }
}

最新更新