我需要检测TableView
行的双击。
我如何监听行的任何部分上的双击,并获取此行的所有数据以将其打印到控制台?
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
,然后打印出该项目的名称?实际数据什么时候涉及进来呢? - HeyPropertyValueFactory
被用于 cellValueFactory
,而不是 cellFactory
。你总是需要在你的 TableColumn
上有一个 cellValueFactory
(请注意表中的两列也都定义了 cellValueFactory
)。如果需要,你还可以在一些或所有列上另外定义 cellFactory
,它们是独立的。我不确定我理解你最后的问题;你提到的代码位于鼠标处理程序中。因此,当鼠标在行上双击时,处理程序将检索该行的值并显示其名称。 - James_DValueFactory
和CellFactory
之间的区别,谢谢。至于我的第二个问题,我刚才没注意到上下文,现在我明白了。 - Hey例子:
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()
才能使我的代码正常工作。 - Johistable.setOnMouseClicked((MouseEvent event) -> {
if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2){
System.out.println(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的答案中所示。 - Adam Silenko在上一个答案的基础上进行扩展:
额外的检查确保所选行被双击 - 忽略空行或列标题的双击
table.setRowFactory(param -> {
TableRow<MyType> row = new TableRow<>();
row.setOnMouseClicked(event -> Optional.ofNullable(row.getItem()).ifPresent(rowData-> {
if(event.getClickCount() == 2 && rowData.equals(table.getSelectionModel().getSelectedItem())){
System.out.println(rowData);
}
}));
return row;
});
```
我曾经遇到过类似的问题,无法在TableView上检测到鼠标双击事件。 所有的示例都能够完美地工作,但我的应用程序却根本无法检测到双击事件。
后来我发现,如果TableView处于可编辑状态,就无法检测到鼠标双击事件!!
请检查您的应用程序是否像这样处于可编辑状态。
tableView.setEditable( true );
如果条件成立,则双击事件仅在选择了相同的行时触发。
这个答案已经经过测试:
table.setOnMouseClicked( event -> {
if( event.getClickCount() == 2 ) {
System.out.println( table.getSelectionModel().getSelectedItem());
}});
table.getSelectionModel().getSelectedItem()
可以用于双击事件处理。在第一次单击时会移动选择,而在第二次时执行此处理程序。
getTableRow().getItem()
来获取该行的项目。不过更好的方法是直接向表行注册侦听器(请参见答案)。 - James_D