我们要在表中创建一个组合框。每个组合框应基于行具有不同的选项。在我们的示例中,我们有一个具有不同服务器IP地址的表,以及一个包含该服务器上所有用户的组合框。
我们不知道如何在CellFactory内的组合框中填充不同的选项,而且我们不确定如何将comboxbox条目与相应的模型绑定。
我们创建了一个示例,也许有人有主意:
凭据模型
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class CredentialModel {
private StringProperty username = new SimpleStringProperty();
private StringProperty password = new SimpleStringProperty();
public CredentialModel(String username, String password) {
setUsername(username);
setPassword(password);
}
public String getUsername() {
return username.get();
}
public StringProperty usernameProperty() {
return username;
}
public void setUsername(String username) {
this.username.set(username);
}
public String getPassword() {
return password.get();
}
public StringProperty passwordProperty() {
return password;
}
public void setPassword(String password) {
this.password.set(password);
}
}
ServerModel
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class ServerModel {
private IntegerProperty id = new SimpleIntegerProperty();
private StringProperty ip = new SimpleStringProperty();
private ObjectProperty<CredentialModel> credential = new SimpleObjectProperty<>();
private ObservableList<CredentialModel> allCredentials = FXCollections.observableArrayList();
public ObservableList<CredentialModel> getAllCredentials() {
return allCredentials;
}
public void setAllCredentials(ObservableList<CredentialModel> allCredentials) {
this.allCredentials = allCredentials;
}
public ServerModel(Integer id, String ip) {
setId(id);
setIp(ip);
}
public String getIp() {
return ip.get();
}
public StringProperty ipProperty() {
return ip;
}
public void setIp(String ip) {
this.ip.set(ip);
}
public CredentialModel getCredential() {
return credential.get();
}
public ObjectProperty<CredentialModel> credentialProperty() {
return credential;
}
public void setCredential(CredentialModel credential) {
this.credential.set(credential);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
}
主应用程序 TableApplication
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TableApplication extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
VBox box = new VBox();
TableView<ServerModel> tableView = new TableView<>();
TableColumn<ServerModel, String> ipColumn = new TableColumn<>("IP-Address");
TableColumn<ServerModel, CredentialModel> userColumn = new TableColumn<>("Username");
tableView.getColumns().addAll(ipColumn, userColumn);
ipColumn.setCellValueFactory(param -> param.getValue().ipProperty());
tableView.getItems().addAll(populateTable());
userColumn.setCellFactory(new Callback<TableColumn<ServerModel,CredentialModel>, TableCell<ServerModel,CredentialModel>>() {
@Override
public TableCell<ServerModel, CredentialModel> call(TableColumn<ServerModel, CredentialModel> param) {
return new UserComboBoxTableCell();
}
});
Button button = new Button("Start");
button.setOnAction(event -> System.out.println(tableView.getSelectionModel().getSelectedItem().getCredential().getUsername()));
box.getChildren().addAll(tableView, button);
Scene scene = new Scene(box,800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private ObservableList<ServerModel> populateTable() {
ServerModel serverModel1 = new ServerModel(1, "192.168.0.1");
serverModel1.setAllCredentials(FXCollections.observableArrayList(new CredentialModel("user1", "pw1"), new CredentialModel("user2", "pw2")));
ServerModel serverModel2 = new ServerModel(2, "192.168.0.2");
serverModel2.setAllCredentials(FXCollections.observableArrayList(new CredentialModel("user3", "pw3")));
return FXCollections.observableArrayList(serverModel1, serverModel2);
}
和TableCellClass UserComboBoxTableCell
import javafx.scene.control.ComboBox;
import javafx.scene.control.TableCell;
public class UserComboBoxTableCell extends TableCell<ServerModel, CredentialModel> {
public UserComboBoxTableCell() {
}
@Override
protected void updateItem(CredentialModel item, boolean empty) {
super.updateItem(item, empty);
if(empty == false) {
if(getTableRow() != null && getTableView() != null) {
int index = getTableRow().getIndex();
ServerModel serverModel = getTableView().getItems().get(index);
ComboBox<CredentialModel> box = new ComboBox<>(serverModel.getAllCredentials());
box.valueProperty().bindBidirectional(serverModel.credentialProperty());
setGraphic(box);
}
}
}
}
方法 loadCredentials 的想法是,对于每一行,应为“虚拟”调用此方法-为服务器行加载凭据。
该按钮的 onAction 方法的想法是显示所选服务器行中的所选用户名。目前,我们仅打印ip地址,因为凭据始终为null(因为此刻未绑定)。
感谢您的帮助。 豪克
编辑 我只是向服务器添加了一个可观察的凭证模型列表,并以不同的方式填充了列表视图。但是我仍然不确定如何在CellFactory中为组合框设置选项,因为我需要访问该行,并且不确定绑定。
EDIT2 现在正在工作。我更新了上面的示例。