簡體   English   中英

如何查找SWT表列的索引?

[英]How to find index of SWT table column?

我有一個SWT表,它有零行和6列。

當我右鍵單擊任何一個表頭時,如何計算單擊的表列的索引?

我確實在某個時候右鍵單擊為TableHeader Menu編寫了一個CustomTable

此代碼可幫助您在右鍵單擊表頭時檢測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);
                }
            }
        }
    });

以下是一些可以滿足您需求的代碼:

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

它基本上生成一個MapTableColumn存儲為鍵,將位置存儲為值。

另外,您可以遍歷的所有列Table的內Listener ,並比較它們單擊列。 第一種方法(Map)更快但使用更多內存,而第二種方法(迭代)更慢但使用更少的內存。

與上面的示例類似,但沒有使用地圖來存儲索引:

...
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;
}

在表列定義中:

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

這是另一種看法。 它只使用一個股票SWT表,明確地對右擊做出反應,適用於標題和普通行,空表和全表。

此方法使用SWT.MenuDetect偵聽器和“假TableItem”的組合,創建和處理僅用於標識給定位置的列。 我沒有注意到任何不良的視覺副作用,如閃爍或閃光外觀。 這可能是由於虛假物品被放置在事件處理中,在UI的其余部分可以注意到它的存在之前。

SWT.MenuDetect偵聽器對右鍵單擊鼠標事件做出反應。 不是很直觀; name表明它主要用於規范上下文菜單外觀,但它也可以作為一般的右鍵單擊監聽器。 與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;
    }
}

示例應用程序的屏幕截圖,同時顯示控制台輸出

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM