5

我有一个 SWT 表,它有 0 行和 6 列。

当我右键单击任何一个表头时,如何计算被单击的表列的索引?

4

5 回答 5

4

我确实 在某个时候在右键单击上写了一个CustomTablefor 。TableHeader Menu

此代码可帮助您检测TableColumn右键单击表头。但是,当列顺序更改时,此代码会中断。但是您可以通过比较重新排序的列顺序原始列顺序的索引来修复它。

addListener(SWT.MenuDetect, new Listener() {
        @Override
        public void handleEvent(Event e) {
            Point pt = getShell().getDisplay().map(null, CustomTable.this, new Point(e.x, e.y));
            Rectangle clientArea = CustomTable.this.getClientArea();
            boolean header = clientArea.y <= pt.y && pt.y < (clientArea.y + CustomTable.this.getHeaderHeight());
            //code to calculate column of Right click - START
            int width = 0;
            for(int i = 0; i< CustomTable.this.getColumns().length; i++){
                TableColumn tc = CustomTable.this.getColumns()[i];
                if(width < pt.x  &&  pt.x < width + tc.getWidth()){
                    System.out.println("Right Click on " + tc.getText());
                }
                width += tc.getWidth();
            }
            //code to calculate column of Right click - END
            if (header) {
                if(tableMenu != null){
                    tableMenu.setVisible(false);
                }
                CustomTable.super.setMenu(headerMenu);
                headerMenu.setLocation(e.x, e.y);
                headerMenu.setVisible(true);
                e.doit = false;
            } else {
                headerMenu.setVisible(false);
                CustomTable.super.setMenu(tableMenu);
                if(tableMenu != null){
                    tableMenu.setLocation(e.x, e.y);
                    tableMenu.setVisible(true);
                }
            }
        }
    });
于 2013-06-25T22:17:47.480 回答
3

这是一些可以满足您要求的代码:

private static Map<TableColumn, Integer> mapping = new HashMap<TableColumn, Integer>();

public static void main(String[] args)
{
    Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setText("StackOverflow");
    shell.setLayout(new FillLayout());

    Listener listener = new Listener()
    {
        @Override
        public void handleEvent(Event arg0)
        {
            TableColumn column = (TableColumn) arg0.widget;

            System.out.println(mapping.get(column));
        }
    };

    Table table = new Table(shell, SWT.NONE);
    table.setHeaderVisible(true);

    for(int i = 0; i < 5; i++)
    {
        TableColumn column = new TableColumn(table, SWT.NONE);
        column.setText("Column " + i);
        column.addListener(SWT.Selection, listener);
        column.pack();

        mapping.put(column, i);
    }

    shell.pack();
    shell.open();
    while (!shell.isDisposed())
    {
        if (!display.readAndDispatch())
            display.sleep();
    }
    display.dispose();
}

它基本上生成Map存储TableColumn作为键和位置作为值。

或者,您可以遍历 中的所有列Table并将Listener它们与单击的列进行比较。第一种方法(Map)更快但使用更多内存,而第二种方法(迭代)更慢但使用更少内存。

于 2013-06-25T06:33:43.073 回答
1

与上面的示例类似,但不使用映射来存储索引:

...
column.addSelectionListener(getSelectionAdapter1(tbl.getColumnCount()-1));    
...


private SelectionAdapter getSelectionAdapter1(final int index) {
    SelectionAdapter selectionAdapter = new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            System.out.println(index);
        }
    };
    return selectionAdapter;
}
于 2013-06-25T09:45:21.710 回答
0

在表列定义中:

int index = 0;
TableColumn column1 = new TableColumn(table, SWT.NONE);
column1.setText("Column 1 header");
column1.setData(index);
index++;
TableColumn column2 = new TableColumn(table, SWT.NONE);
column2.setText("Column 2 header");
column2.setData(index);
index++;

等等

在处理程序中:

int index = (int) ((TableColumn) e.widget).getData();
于 2016-04-18T12:25:20.700 回答
0

这是另一种看法。它明确地在右键单击时做出反应,适用于标题和普通行,空表和完整表,只使用一个股票 SWT 表。

这种方法使用 SWT.MenuDetect 侦听器和“假 TableItem”的组合,创建和处理只是为了识别给定位置的列。我没有注意到任何不良的视觉副作用,例如闪烁或闪光外观。这可能是由于在 UI 的其余部分可以注意到它的存在之前在事件处理中处理了假项目。

SWT.MenuDetect 侦听器对鼠标右键单击事件作出反应。不是很直观;顾名思义,它主要是为了规范上下文菜单的外观,但它也可以作为一个通用的右键单击侦听器。与 SWT.MouseDown 不同,它也由表头发出。好的!不幸的是,与 SWT.Selection 不同的是,e.widget 引用了整个表,而不仅仅是列或单元格,因此对于我们的目的是无用的,因为它用于 Baz 响应。该列必须通过使用具有物理坐标的低级别方法来检测。

这是代码:

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

/**
 * Table with right click detection that works for table headers and empty
 * tables. It was tested as working for columns reordering, moving or resizing.
 * 
 * @author Espinosa
 */
public class TableWithRightClickDetection {

    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Table with right click detection");
        shell.setLayout(new FillLayout());
        shell.setSize(400, 300);

        final Table table = new Table(shell, SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        int columnCount = 4;
        for (int i = 0; i < columnCount; i++) {
            TableColumn column = new TableColumn(table, SWT.NONE);
            column.setText("Column " + i);
            column.setMoveable(true);
            column.setResizable(true);
            table.getColumn(i).pack();
        }

        table.addListener(SWT.MenuDetect, (e) -> {
            // SWT.MenuDetect reacts on right-click
            // It is emitted by table header, unlike SWT.MouseDown.
            // Also unlike SWT.Selection the e.widget references whole 
            // Table, not just column or cell, unfortunately, so this has 
            // to be detected using low level approach with physical coordinates.
            Point ptAbsolute = new Point(e.x, e.y);
            Point pt = table.toControl(ptAbsolute); // get position relative to the Tree widget
            int colIndex = columnAtPoint(table, pt);
            if (colIndex >= 0) {
                if (pt.y < table.getHeaderHeight())  {  
                    // for Tree/TreeViews negative Y means table header
                    System.out.println("Header right-clicked on column " + colIndex);
                } else {
                    System.out.println("Row right-clicked on column " + colIndex);
                }
            }
            // prevent showing context menu (if there is any declared)
            e.doit = false;
        });

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    /**
     * @return column index for given coordinates relative to the given Table widget
     */
    private static int columnAtPoint(Table table, Point pt) {
        int colIndex = -1;
        // The only way how to get column bounds is to get TableItem
        // But empty table hasn't got any and headers does not count.
        // The only way is to temporarily create one and then immediately dispose.
        TableItem fakeRow = new TableItem(table, 0);
        for (int i = 0; i < table.getColumnCount(); i++) {
            Rectangle rec = fakeRow.getBounds(i);
            // It is safer to use X coordinate comparison directly rather then 
            // rec.contains(pt)
            // This way also works for Tree/TreeViews.
            if ((pt.x > rec.x)  && (pt.x < (rec.x + rec.width))) {
                colIndex = i;
            }
        }
        fakeRow.dispose();
        // Not the most efficient way. Rectangles obtained from "fake row" can be cached 
        // and recomputed on column resizes, moves and swaps.
        return colIndex;
    }
}

示例应用程序的屏幕截图还显示了它的控制台输出

于 2017-05-05T02:09:41.787 回答