【发布时间】:2014-12-21 04:54:57
【问题描述】:
我需要检测对TableView 的一行的双击。
如何监听该行任何部分的双击并获取该行的所有数据以将其打印到控制台?
【问题讨论】:
-
使用双击单元格的解决方案会起作用,因为您始终可以在单元格上调用
getTableRow().getItem()来获取该行的项目。更好的是直接在表格行中注册一个监听器(见答案)。
我需要检测对TableView 的一行的双击。
如何监听该行任何部分的双击并获取该行的所有数据以将其打印到控制台?
【问题讨论】:
getTableRow().getItem() 来获取该行的项目。更好的是直接在表格行中注册一个监听器(见答案)。
我有类似的情况,没有检测到 TableView 上的鼠标双击事件。 最重要的是,样品工作得很好。但我的应用程序根本没有检测到双击事件。
但是我发现如果TableView处于可编辑状态,就无法检测到鼠标双击事件!!
如果 TableView 像这样可编辑,请检查您的应用程序。
tableView.setEditable( true );
如果这样,双击事件只会在选中的同一行上引发。
【讨论】:
这对我有用:
table.setOnMouseClicked((MouseEvent event) -> {
if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2){
System.out.println(table.getSelectionModel().getSelectedItem());
}
});
}
【讨论】:
TableView<MyType> table = new TableView<>();
//...
table.setRowFactory( tv -> {
TableRow<MyType> row = new TableRow<>();
row.setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
MyType rowData = row.getItem();
System.out.println(rowData);
}
});
return row ;
});
这是一个完整的工作示例:
import java.util.Random;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class TableViewDoubleClickOnRow extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setRowFactory(tv -> {
TableRow<Item> row = new TableRow<>();
row.setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (! row.isEmpty()) ) {
Item rowData = row.getItem();
System.out.println("Double click on: "+rowData.getName());
}
});
return row ;
});
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Value", Item::valueProperty));
Random rng = new Random();
for (int i = 1 ; i <= 50 ; i++) {
table.getItems().add(new Item("Item "+i, rng.nextInt(1000)));
}
Scene scene = new Scene(table);
primaryStage.setScene(scene);
primaryStage.show();
}
private static <S,T> TableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
TableColumn<S,T> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
return col ;
}
public static class Item {
private final StringProperty name = new SimpleStringProperty();
private final IntegerProperty value = new SimpleIntegerProperty();
public Item(String name, int value) {
setName(name);
setValue(value);
}
public StringProperty nameProperty() {
return name ;
}
public final String getName() {
return nameProperty().get();
}
public final void setName(String name) {
nameProperty().set(name);
}
public IntegerProperty valueProperty() {
return value ;
}
public final int getValue() {
return valueProperty().get();
}
public final void setValue(int value) {
valueProperty().set(value);
}
}
public static void main(String[] args) {
launch(args);
}
}
【讨论】:
PropertyValueFactory 的代码,如何扩展您的方法来监听双击?另外,我不明白你的行工厂的这一部分:你创建一个新的TableRow,在上面调用getItem,然后打印这个项目的名称?何时涉及实际数据?
PropertyValueFactory 用于cellValueFactory,而不是cellFactory。您的TableColumns 上始终需要cellValueFactory(请注意,表中的两列也都定义了cellValueFactorys)。如果需要,您可以在部分或全部列上另外定义cellFactorys;他们独立于此。不确定我是否理解您的最后一个问题;您所指的代码在鼠标处理程序中。因此,当鼠标双击该行时,处理程序会检索该行的值并显示其名称。
ValueFactory 和CellFactory 之间的区别,谢谢。至于我的第二个问题,我只是错过了上下文,我现在明白了。
这个答案已经过测试:
table.setOnMouseClicked( event -> {
if( event.getClickCount() == 2 ) {
System.out.println( table.getSelectionModel().getSelectedItem());
}});
table.getSelectionModel().getSelectedItem() 可以使用,因为我们双击。第一次单击选择移动,第二次执行此处理程序。
【讨论】:
如果您使用SceneBuilder,您可以将您的表的OnMouseClicked 设置为handleRowSelect() 方法,如下所示:
MyType temp;
Date lastClickTime;
@FXML
private void handleRowSelect() {
MyType row = myTableView.getSelectionModel().getSelectedItem();
if (row == null) return;
if(row != temp){
temp = row;
lastClickTime = new Date();
} else if(row == temp) {
Date now = new Date();
long diff = now.getTime() - lastClickTime.getTime();
if (diff < 300){ //another click registered in 300 millis
System.out.println("Edit dialog");
} else {
lastClickTime = new Date();
}
}
}
【讨论】:
handleRowSelect(MouseEvent event) 来检测与@Abdul.Moqueet 回答中的主要鼠标按钮的双击
例子:
table.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isPrimaryButtonDown() && event.getClickCount() == 2) {
System.out.println(table.getSelectionModel().getSelectedItem());
}
}
});
如果您使用自定义选择模型,则可以从事件中获取行,例如:
table.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isPrimaryButtonDown() && event.getClickCount() == 2) {
Node node = ((Node) event.getTarget()).getParent();
TableRow row;
if (node instanceof TableRow) {
row = (TableRow) node;
} else {
// clicking on text part
row = (TableRow) node.getParent();
}
System.out.println(row.getItem());
}
}
});
【讨论】:
event.getButton().equals(MouseButton.PRIMARY) 而不是 event.isPrimaryButtonDown() 才能让我的工作。