【发布时间】:2019-07-11 08:39:59
【问题描述】:
目前在 TableView 中,当我们单击鼠标中键时不会发生行选择。如果我们右键或左键单击,则选择该行。我正在尝试具有在单击中间按钮时选择行的功能。
我已经知道在表格行工厂中包含一个事件处理程序可以解决这个问题。但是我有一个自定义表格视图,其中包含许多适用于我的应用程序的自定义功能。这个自定义的 TableView 在我的应用程序中被广泛使用。我的主要问题是,我不能要求每个表格行工厂都包含此修复程序。
我正在寻找一种在更高级别(可能在 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.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableRowSelectionOnMiddleButtonDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<Person> persons = FXCollections.observableArrayList();
for (int i = 0; i < 4; i++) {
persons.add(new Person("First name" + i, "Last Name" + i));
}
CustomTableView<Person> tableView = new CustomTableView<>();
TableColumn<Person, String> fnCol = new TableColumn<>("First Name");
fnCol.setCellValueFactory(param -> param.getValue().firstNameProperty());
TableColumn<Person, String> lnCol = new TableColumn<>("Last Name");
lnCol.setCellValueFactory(param -> param.getValue().lastNameProperty());
tableView.getColumns().addAll(fnCol, lnCol);
tableView.getItems().addAll(persons);
tableView.setRowFactory(new Callback<TableView<Person>, TableRow<Person>>() {
@Override
public TableRow<Person> call(TableView<Person> param) {
return new TableRow<Person>(){
{
/* This will fix my issue, but I dont want each tableView rowfactory to set this behavior.*/
// addEventHandler(MouseEvent.MOUSE_PRESSED,e->{
// getTableView().getSelectionModel().select(getItem());
// });
}
@Override
protected void updateItem(Person item, boolean empty) {
super.updateItem(item, empty);
}
};
}
});
VBox sp = new VBox();
sp.setAlignment(Pos.TOP_LEFT);
sp.getChildren().addAll(tableView);
Scene sc = new Scene(sp);
primaryStage.setScene(sc);
primaryStage.show();
}
public static void main(String... a) {
Application.launch(a);
}
/**
* My custom tableView.
* @param <S>
*/
class CustomTableView<S> extends TableView<S> {
public CustomTableView() {
// A lot of custom behavior is included to this TableView.
}
}
class Person {
private StringProperty firstName = new SimpleStringProperty();
private StringProperty lastName = new SimpleStringProperty();
public Person(String fn, String ln) {
setFirstName(fn);
setLastName(ln);
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public String getLastName() {
return lastName.get();
}
public StringProperty lastNameProperty() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName.set(lastName);
}
}
}
【问题讨论】:
-
使用自定义
rowFactory几乎是在TableView级别处理这个问题。执行此操作的任何其他方式至少要复杂两倍,并且其中大多数方式更难维护。如果您害怕失去使用自定义rowFactory添加的其他一些功能,那么调整由另一个行工厂创建的行非常容易。使用自定义rowFactory是解决此问题的最佳方法,我无法找到不使用此方法的理由。(您不需要为每个TableView一遍又一遍地编写此代码您创建的应该获得该功能。) -
@fabian 感谢您的建议。如果我能用更少的努力调整,我会再试一次,否则会听从你的建议。