Переупорядочивание SWT/JFace TreeColumn - проблема с setMoveable()

Я пытаюсь настроить многоколоночный 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();
    }
}

person Dave Hartnoll    schedule 16.09.2011    source источник


Ответы (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);
            }
        });
    }
}
person mecsco    schedule 16.09.2011
comment
Спасибо за это предложение. Я немного разочарован тем, что, по-видимому, нет (простого) способа предотвратить перетаскивание столбца в изначально недопустимое место, особенно на Mac, поскольку столбцы визуально переупорядочиваются во время операции перетаскивания. Я выбрал немного более компактный вариант вашей идеи, который я опубликую как отдельный ответ. - person Dave Hartnoll; 19.09.2011

Вот мое окончательное решение, основанное на ответе 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();
        }
    }
person Dave Hartnoll    schedule 19.09.2011
comment
Дэйв, я использую TableViewerColumn и TableLAyout и хочу добиться того же. Любая идея, как я могу контролировать порядок столбцов там? - person user523956; 07.11.2014
comment
Извините, я недостаточно знаком с JFace/SWT, чтобы знать, можно ли адаптировать это решение. Я предлагаю вам опубликовать отдельный вопрос и, возможно, дать ссылку на этот. - person Dave Hartnoll; 07.11.2014