SWT表格批量移除Button单元格问题求助
你遇到的核心问题是没有维护每行按钮和TableEditor的引用集合——当前你把operationButtons、removeButtons、checkButtons定义为单个变量,每次添加新行时都会覆盖之前的引用,导致Remove All时只能处理最后一行的组件。下面针对你的两个需求给出具体解决方案:
1. 批量移除所有Button和TableEditor组件
最可靠的方式是自己维护每行创建的按钮和编辑器引用,这样批量操作时可以精准遍历处理:
步骤1:定义集合存储组件引用
在Test类中添加几个集合,用来保存所有行的按钮和TableEditor:
private List<Button> allCheckButtons = new ArrayList<>(); private List<Button> allRemoveButtons = new ArrayList<>(); private List<Button> allOperationButtons = new ArrayList<>(); private List<TableEditor> allTableEditors = new ArrayList<>();
步骤2:添加行时将组件存入集合
在dateReceived方法中,创建每个按钮和TableEditor后,立即添加到对应集合:
// 创建复选框按钮并加入集合 checkButtons = new Button(table, SWT.CHECK); allCheckButtons.add(checkButtons); // 创建移除按钮并加入集合 removeButtons = new Button(table, SWT.PUSH); allRemoveButtons.add(removeButtons); // 创建操作按钮并加入集合 operationButtons = new Button(table, SWT.PUSH); allOperationButtons.add(operationButtons); // 将三个TableEditor加入集合 allTableEditors.add(checkEditors); allTableEditors.add(removeEditors); allTableEditors.add(operationEditors);
步骤3:Remove All时批量销毁组件
修改Remove All按钮的监听器,遍历集合销毁所有组件并清空集合,最后清除表格行:
button.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { // 销毁所有按钮(先判断是否已销毁,避免异常) for (Button btn : allCheckButtons) { if (!btn.isDisposed()) btn.dispose(); } for (Button btn : allRemoveButtons) { if (!btn.isDisposed()) btn.dispose(); } for (Button btn : allOperationButtons) { if (!btn.isDisposed()) btn.dispose(); } // 销毁所有TableEditor for (TableEditor editor : allTableEditors) { editor.dispose(); } // 清空集合,避免内存泄漏 allCheckButtons.clear(); allRemoveButtons.clear(); allOperationButtons.clear(); allTableEditors.clear(); // 清除表格行数据 table.removeAll(); // 重新布局组件 composite.layout(true, true); } });
这种方式比遍历table.getChildren()更精准,不会误删表格内的其他控件,也能确保所有组件都被正确销毁。
2. 获取每个Button所在行的索引
可以通过SWT控件的setData()和getData()方法,将按钮与对应的TableItem或行索引关联起来,具体有两种方式:
方式一:关联TableItem(推荐)
在创建按钮时,把对应的TableItem存入按钮的自定义数据中:
// 在dateReceived方法中创建removeButtons后添加 removeButtons.setData("tableItem", item);
然后在按钮的Selection监听器中,取出TableItem并获取当前行索引:
removeButtons.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event e) { Button currentBtn = (Button) e.widget; // 获取关联的TableItem TableItem item = (TableItem) currentBtn.getData("tableItem"); // 获取当前行索引(实时更新,不受行删除影响) int rowIndex = table.indexOf(item); // 后续业务逻辑... MessageBox messageBox = new MessageBox(composite.getShell(), SWT.ICON_QUESTION | SWT.YES | SWT.NO); messageBox.setMessage("Do you really want to remove row " + rowIndex + "?"); // ... } });
这种方式的优势是,即使表格行被删除或顺序变化,table.indexOf(item)也能获取到当前最新的行索引。
方式二:直接存储行索引
如果不需要实时索引,也可以在创建行时直接把索引存入按钮:
// 在dateReceived方法中创建按钮后 int currentRowIndex = table.indexOf(item); removeButtons.setData("rowIndex", currentRowIndex);
然后在监听器中直接取出:
int rowIndex = (int) currentBtn.getData("rowIndex");
注意:这种方式的索引是创建行时的初始索引,如果后续有行被删除,这个索引会和实际行位置不符,所以更推荐方式一。
内容的提问来源于stack exchange,提问作者krezus

