如何在JavaFX TableView中实现双击不进入编辑模式,同时保留单击编辑功能?
如何在JavaFX TableView中实现双击不进入编辑模式,同时保留单击编辑功能?
我明白你的需求啦,现在的问题是双击时会同时触发自定义操作和编辑模式,咱们得把编辑模式给拦下来,同时保留其他的默认行为。下面给你一个可行的解决方案:
核心思路是标记双击事件的状态,在编辑开始前检查这个状态,如果是双击导致的编辑触发,就取消这次编辑,同时确保双击时能正常选中单元格并执行自定义操作。
修改后的完整代码
import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import javafx.scene.control.cell.TextFieldTableCell; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.concurrent.atomic.AtomicBoolean; public class NewMain1 extends Application { public static class Person { private final StringProperty firstName; private final StringProperty lastName; public Person(String firstName, String lastName) { this.firstName = new SimpleStringProperty(firstName); this.lastName = new SimpleStringProperty(lastName); } public StringProperty firstNameProperty() { return firstName; } public StringProperty lastNameProperty() { return lastName; } } @Override public void start(Stage primaryStage) { TableView<Person> tableView = new TableView<>(); tableView.setEditable(true); // 用来标记是否是双击事件导致的编辑触发 AtomicBoolean isDoubleClick = new AtomicBoolean(false); TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name"); firstNameCol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty()); firstNameCol.setCellFactory(TextFieldTableCell.forTableColumn()); firstNameCol.setOnEditStart(e -> { // 如果是双击触发的编辑,就取消操作 if (isDoubleClick.get()) { e.consume(); isDoubleClick.set(false); } else { System.out.println("First Name Edit Start"); } }); TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name"); lastNameCol.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty()); lastNameCol.setCellFactory(TextFieldTableCell.forTableColumn()); lastNameCol.setOnEditStart(e -> { if (isDoubleClick.get()) { e.consume(); isDoubleClick.set(false); } else { System.out.println("Last Name Edit Start"); } }); tableView.getColumns().addAll(firstNameCol, lastNameCol); ObservableList<Person> data = FXCollections.observableArrayList( new Person("John", "Smith"), new Person("Emily", "Johnson"), new Person("Michael", "Williams"), new Person("Sarah", "Brown") ); tableView.setItems(data); tableView.setRowFactory(tv -> { TableRow<Person> row = new TableRow<>(); row.setOnMouseClicked(event -> { if (event.getClickCount() == 2 && !row.isEmpty()) { Person person = row.getItem(); // 执行自定义操作 System.out.println("DoubleClick on " + person.firstNameProperty().get() + " " + person.lastNameProperty().get()); // 标记为双击事件 isDoubleClick.set(true); // 确保双击时选中当前行/单元格 tableView.getSelectionModel().select(row.getIndex()); // 消耗事件,避免后续不必要的事件传递 event.consume(); } else { // 非双击事件,重置标记 isDoubleClick.set(false); } }); return row; }); VBox root = new VBox(tableView); Scene scene = new Scene(root, 400, 300); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
方案说明
- 标记双击事件:用
AtomicBoolean来记录当前是否是双击操作,因为要在Lambda表达式中修改这个状态,所以用原子类保证线程安全。 - 双击事件处理:在TableRow的鼠标点击事件中,检测到双击时:
- 执行你的自定义逻辑
- 标记
isDoubleClick为true - 手动选中当前行(确保双击时能选中目标单元格)
- 消耗事件,减少不必要的事件传递
- 拦截双击导致的编辑:在每个列的
onEditStart事件中,检查isDoubleClick状态:- 如果是双击导致的编辑触发,就调用
e.consume()取消编辑 - 重置
isDoubleClick状态,不影响后续的单击操作
- 如果是双击导致的编辑触发,就调用
这样修改后,就能完美满足你的所有需求:
- 单击未选中单元格:正常选中
- 单击已选中单元格:正常进入编辑模式
- 双击单元格:选中(如果未选中)+ 仅执行自定义操作,不会进入编辑模式
备注:内容来源于stack exchange,提问作者SilverCube
相关产品推荐
相关产品推荐

