2013-06-25 80 views
4

我有一个SWT表,它有零行和6列。 当我右键单击表头中的任何一个,我如何计算 表右列的右键单击索引? 请给一些片段。如何找到SWT表列的索引

在此先感谢 佳日

回答

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关键和值的位置。

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

+0

感谢很多不错的片断:)这是工作,而列选择罚款,而列右键单击。我试图修改SWT.Selection SWT.MouseDown没有运气。任何输入? – yash

+0

@yash有一个相当古老的bug报告[这里](https://bugs.eclipse.org/bugs/show_bug.cgi?id=32322)表明'TableColumn'头不支持右键单击。 – Baz

+0

@yash但是,如果您使用的是右键单击菜单,则可以查看[this](http://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples /org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet311.java)代码示例并使用'SWT.MenuDetect'。 – Baz

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; 
} 
+0

请注意,这仅在列未移动时才有效。只要列被移动,您就必须使用table.getColumnOrder()来确定列的索引。 – halfpad

4

我做了右键单击一个CustomTableTableHeaderMenu写回的某个时候。

此代码可帮助您检测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); 
       } 
      } 
     } 
    }); 
+0

如果表格控件的水平滚动条不在开始位置,此代码是否可以工作? –

+0

@MikeNakis它应该,因为headerHeight和clientArea计算w.r.t滚动条,如果存在。试一试。 – Niranjan

+0

我不认为clientArea是计算w.r.t滚动条,在任何情况下,您的计算中都没有使用clientArea.x来查找列,所以在我看来,即使clientArea受到滚动的影响,它也不起作用。既然你已经有了代码,这大概是你写的一些应用程序的一部分,你为什么不尝试并告诉我们? –

0

在TableColumn的定义:

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

screenshot from the example app showing also console output from it