Java SWT/JFace树柱重新排序-setMoveable()问题

Java SWT/JFace树柱重新排序-setMoveable()问题,java,tree,swt,jface,treeviewer,Java,Tree,Swt,Jface,Treeviewer,我正在尝试设置一个多列SWT树(通过JFaceTreeViewer),允许用户通过拖动列标题对其列重新排序。但是,第一列应保持固定和不可移动。我可以在每个treecocolumn上使用setMoveable(true)方法,但第一个要真正接近的列除外,但这并不妨碍用户将不同的列拖动到它的左侧。有没有办法解决这个问题 下面是一个简化的工作片段(没有JFace)来说明问题: import org.eclipse.swt.SWT; import org.eclipse.swt.layout.RowDa

我正在尝试设置一个多列SWT
(通过JFace
TreeViewer
),允许用户通过拖动列标题对其列重新排序。但是,第一列应保持固定和不可移动。我可以在每个
treecocolumn
上使用
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();
    }
}
import org.eclipse.swt.swt;
导入org.eclipse.swt.layout.RowData;
导入org.eclipse.swt.layout.RowLayout;
导入org.eclipse.swt.widgets.Display;
导入org.eclipse.swt.widgets.Shell;
导入org.eclipse.swt.widgets.Tree;
导入org.eclipse.swt.widgets.treecocolumn;
导入org.eclipse.swt.widgets.TreeItem;
公共类TreeTableColumnMove{
公共静态void main(字符串[]args){
显示=新显示();
外壳=新外壳(显示);
shell.setLayout(新的行布局(SWT.HORIZONTAL));
树=新树(外壳,SWT.BORDER | SWT.CHECK);
setLayoutData(新的行数据(-1100));
tree.setheadervible(true);
对于(int i=0;i<5;i++){
树柱=新的树柱(树,SWT.CENTER);
列.setText(“列”+i);
列宽(60);
如果(i>0)column.setMoveable(true);
}
TreeItem=新的TreeItem(树,SWT.NONE);
item.setText(新字符串[]{“c0”、“c1”、“c2”、“c3”、“c4”});
shell.pack();
shell.open();
而(!shell.isDisposed()){
如果(!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
}

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

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

请注意,无论视觉顺序如何,创建的第一列始终为零(依此类推)。方法tree.getColumnOrder()将以可视化方式排序,值是创建的顺序索引(因此,如果交换第2列和第3列,该方法将返回[0,2,1,3,4])

for(int i=0;i<5;i++){
树柱=新的树柱(树,SWT.CENTER);
列.setText(“列”+i);
列宽(60);
如果(i>0)column.setMoveable(true);
//这里有新代码
如果(i==0){
column.addControlListener(新的ControlAdapter(){
公共无效控制移动(控制事件e){
List newOrder=newarraylist();
//添加第一个
newOrder.add(0);
//围绕所有列循环
for(int col:tree.getColumnOrder()){
//如果不是第一个添加的,请添加到列表
如果(列!=0){
newOrder.add(col);
}
}
//将列表转换为数组
int[]newOrderArray=newint[newOrder.size()];
对于(int j=0;j
以下是我根据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();
        }
    }
import org.eclipse.swt.swt;
导入org.eclipse.swt.layout.RowData;
导入org.eclipse.swt.layout.RowLayout;
导入org.eclipse.swt.widgets.Display;
导入org.eclipse.swt.widgets.Event;
导入org.eclipse.swt.widgets.Listener;
导入org.eclipse.swt.widgets.Shell;
导入org.eclipse.swt.widgets.Tree;
导入org.eclipse.swt.widgets.treecocolumn;
导入org.eclipse.swt.widgets.TreeItem;
公共类TreeTableColumnMove{
公共静态void main(字符串[]args){
显示=新显示();
外壳=新外壳(显示);
shell.setLayout(新的行布局(SWT.HORIZONTAL));
最终树=新树(外壳,SWT.BORDER | SWT.CHECK);
setLayoutData(新的行数据(-1100));
tree.setheadervible(true);
Listener moveListener=new Listener(){
公共无效handleEvent(事件e){
int[]order=tree.getColumnOrder();

对于(inti=0,col=0;我赞成这个建议。我有点失望,显然没有(简单的)防止将列拖放到初始无效位置的方法,尤其是在Mac上,因为在拖动操作过程中,列会被直观地重新排序。我采用了您的想法的一个稍微紧凑的变体,我将作为单独的答案发布。Dave,我正在使用TableViewerColumn和TableLAyout,希望实现同样的精简g、 你知道我该如何控制那里的列顺序吗?对不起,我对JFace/SWT不够熟悉,无法马上知道这个解决方案是否可以修改。我建议你发布一个单独的问题,也许可以链接到这个问题。
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();
        }
    }