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

发布于 2024-12-05 02:25:34 字数 1543 浏览 1 评论 0原文

我正在尝试设置一个多列 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();
    }
}

I am trying to set up a multi-column SWT Tree (via a JFace TreeViewer) that allows its columns to be re-ordered by the user by dragging the column headers. However, the first column should remain fixed and unmoveable. I can use the setMoveable(true) method on each TreeColumn except the first to get real close, but that doesn't prevent the user dragging a different column to the left of it. Any ideas how to resolve this?

Here's a simplified working snippet (without JFace) to illustrate the problem:

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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月依秋水 2024-12-12 02:25:34

这是我根据 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();
        }
    }

Here is my final solution based on danmec's answer:

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();
        }
    }
做个ˇ局外人 2024-12-12 02:25:34

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

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

请注意,无论视觉顺序如何,创建的第一列始终为零(依此类推)。方法 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);
            }
        });
    }
}

I don't know if it's possible to actually prevent it, but you can handle the result of the column moving, and react to it to achieve what you want.

Maybe something along these lines would be a good starting point? Essentially it listens for the first column being moved (not directly, but being shifted as a result of another column being moved to the left of it), and then re-shuffles the order so it is the first column visually again.

Note that regardless of the visual order, the first column created will always be zero (and so on). The method tree.getColumnOrder() will be ordered visually, with the values being the created order indexes (so if you swap the 2nd and 3rd columns, the method will return [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);
            }
        });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文