我有一个SWT表,它有零行和6列。
当我右键单击任何一个表头时,如何计算所单击的表列的索引?
答案 0 :(得分:4)
我确实为CustomTable
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);
}
}
}
});
答案 1 :(得分: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)更快但使用更多内存,而第二种方法(迭代)更慢但使用更少的内存。
答案 2 :(得分: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;
}
答案 3 :(得分: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();
答案 4 :(得分:0)
这是另一种看法。它只使用股票SWT表就可以明确地对右键单击做出反应,适用于标题和普通行,空表和完整表格。
此方法使用SWT.MenuDetect侦听器和&#34;伪TableItem&#34;的组合,创建和处理仅用于识别给定位置的列。我没有注意到任何不良的视觉副作用,如闪烁或闪光外观。这可能是由于虚假物品被放置在事件处理中,在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;
}
}