4

我正在尝试设置一个多列 SWT Tree(通过 JFace TreeViewer),它允许用户通过拖动列标题来重新排序其列。但是,第一列应保持固定且不可移动。除了第一个方法之外,我可以setMoveable(true)在每个方法上使用该方法TreeColumn来真正关闭,但这并不能阻止用户将不同的列拖到它的左侧。任何想法如何解决这个问题?

这是一个简化的工作片段(没有 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();
    }
}
4

2 回答 2

3

这是我基于 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();
        }
    }
于 2011-09-19T09:34:07.183 回答
2

我不知道是否可以实际阻止它,但是您可以处理列移动的结果,并对它做出反应以实现您想要的。

也许这些方面的东西会是一个很好的起点?本质上,它侦听第一列被移动(不是直接移动,而是由于另一列被移动到它的左侧而被移动),然后重新调整顺序,使其再次成为视觉上的第一列。

请注意,无论视觉顺序如何,创建的第一列将始终为零(依此类推)。方法 tree.getColumnOrder() 将以视觉方式排序,其值是创建的顺序索引(因此,如果交换第 2 列和第 3 列,该方法将返回 [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);
            }
        });
    }
}
于 2011-09-16T14:58:37.983 回答