- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
JavaFX:如何在新场景中更新 observableArrayList 中选定的项目。没有传递整组数据支持吗?
我认为将一个选定的项目传递到新窗口是有意义的。我无法通过这样做让 observableArrayList 反射(reflect)更改。
我只能通过传递整个数据集来让我的程序运行。支持 observableArrayList 的 ArrayList 和 observableArrayList 本身。然后在ArrayList中查找元素,修改该元素,将元素重新插入到列表中,然后清除整个ArrayList并将其重新添加到observableArrayList中。我确信这不是最好的方法。作为 Javafx 的新手,我不确定如何进行这项工作。
这是我如何完成此工作的一个工作示例。希望这能凸显出我做错了什么以及我需要改变什么。
请注意:如果可能的话,我不想使用任何静态类。这是一个小项目,我计划扩展到更大的项目,并且我想避免使用静态类的陷阱。
请注意:我省略了过帐导入。假设我有正确的导入。
目录结构。
--example
main.fxml
Main.java
MainController.java
modify.fxml
ModifyController.java
myData.java
Main.java
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
ArrayList<myData> values = new ArrayList<>();
values.add(new myData("1"));
values.add(new myData("2"));
values.add(new myData("3"));
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
Parent root = loader.load();
MainController myController = loader.getController();
myController.initialize(values);
primaryStage.setTitle("Hello World");
Scene mainScene = new Scene(root);
primaryStage.setScene(mainScene);
myController.setMainStage(primaryStage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
MainController.java
public class MainController {
@FXML
private Button modifyButton;
@FXML
private TableView<myData> valueTable;
@FXML
private TableColumn valueCell;
private ObservableList<myData> observableDataModels;
private ArrayList<myData> values;
private Stage primaryStage;
public void initialize(ArrayList<myData> values) {
this.values = values;
this.observableDataModels = FXCollections.observableArrayList(values);
this.valueCell.setCellValueFactory(new PropertyValueFactory<>("value"));
this.valueTable.setItems(observableDataModels);
}
public void setMainStage(Stage primaryStage) {
this.primaryStage = primaryStage;
}
public void onMouseClicked(MouseEvent mouseEvent) throws IOException {
if (!this.valueTable.getSelectionModel().getSelectedCells().isEmpty()) {
myData selectedItem = this.valueTable.getSelectionModel().getSelectedItem();
FXMLLoader loader = new FXMLLoader(getClass().getResource("modify.fxml"));
Parent root = loader.load();
ModifyController mpc = loader.getController();
mpc.setData(selectedItem);
mpc.setObservableDataModels(this.observableDataModels);
mpc.setValues(this.values);
TextField t = mpc.getValueTxtFld();
t.setText(selectedItem.getValue());
mpc.setValueTxtFld(t);
Stage modifyStage = new Stage();
Scene modfifyPartScene = new Scene(root);
modifyStage.setScene(modfifyPartScene);
mpc.setCurrStage(modifyStage);
modifyStage.show();
}
}
}
ModifyController.java
public class ModifyController {
@FXML
private TextField valueTxtFld;
@FXML
private Button mdfSaveBtn;
@FXML
private Stage currStage;
private myData data;
private ObservableList<myData> observableDataModels;
private ArrayList<myData> values;
public void setObservableDataModels(
ObservableList<myData> observableDataModels) {
this.observableDataModels = observableDataModels;
}
public ArrayList<myData> getValues() {
return values;
}
public void setValues(ArrayList<myData> values) {
this.values = values;
}
public TextField getValueTxtFld() {
return valueTxtFld;
}
public void setValueTxtFld(TextField valueTxtFld) {
this.valueTxtFld = valueTxtFld;
}
public void setData(myData selectedItem) {
this.data = selectedItem;
}
public void setCurrStage(Stage modifyStage) {
this.currStage = modifyStage;
}
public void onMouseClicked(MouseEvent mouseEvent) {
myData dataBuffer = this.data;
int i = dataBuffer.hashCode();
this.data.setValue(this.valueTxtFld.getText());
int count = 0;
for (myData d : values) {
if (i == d.hashCode()) {
values.remove(count);
values.set(count, this.data);
} else {
count += 1;
}
}
observableDataModels.removeAll(values);
observableDataModels.addAll(values);
this.currStage.close();
}
}
main.fxml
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="example.ModifyController">
<children>
<TextField fx:id="valueTxtFld" layoutX="193.0" layoutY="169.0" />
<Button fx:id="mdfSaveBtn" layoutX="261.0" layoutY="219.0" mnemonicParsing="false" onMouseClicked="#onMouseClicked" text="Save" />
</children>
</AnchorPane>
修改.fxml
<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="example.ModifyController">
<children>
<TextField fx:id="valueTxtFld" layoutX="193.0" layoutY="169.0" />
<Button fx:id="mdfSaveBtn" layoutX="261.0" layoutY="219.0" mnemonicParsing="false" onMouseClicked="#onMouseClicked" text="Save" />
</children>
</AnchorPane>
最佳答案
您正在编辑单个项目。由于这个原因,您不应该列出 list 。 Stage.showAndWait
允许您等待用户完成输入并对其使用react,我强烈建议您这样做。
除此之外,我还建议更改以下几项内容:
onAction
事件,而不是 onMouseClicked
事件。这样,当按钮获得焦点时,您还可以对按 Enter 键使用react,并防止使用主按钮以外的鼠标按钮进行点击来触发该按钮。selectedItem
而不是选定的单元格。这两个是独立的东西,检查 null
并不比在某个列表上调用 isEmpty()
更难。valueTxtFld
属性的 setter 使代码更加困惑,因为您最终可能会得到一个不属于场景的 TextField
:您可以传递不同的 TextField
比 getValueTxtFld
返回到 setValueTxtFld
导致的错误不是最简单的调试错误。如果您只是提供对正在使用的属性(TextField.text
属性)的访问权限,那么这不会成为问题。但在这种情况下,不需要访问权限。迭代列表时不要修改列表。您可能会收到 ConcurrentModificationException
。也不要用比较哈希码来代替检查相等性。这比必要的更复杂并且可能会失败。 (假设您的 hashCode
实现仅基于 String
值,则每个可能的 int
都有一个字符串,并且有些字符串不包含int
值,因此必须有 2 个不同的对象具有相同的哈希码)。
只需使用 indexOf
即可:
int index = values.indexOf(data);
values.set(index, ...);
main.fxml
<Button fx:id="mdfSaveBtn" layoutX="261.0" layoutY="219.0" mnemonicParsing="false" onAction="#modify" text="Save" />
修改.fxml
<Button fx:id="mdfSaveBtn" layoutX="261.0" layoutY="219.0" mnemonicParsing="false" onAction="#save" text="Save" />
public class MainController {
...
// you can leave out the event parameter here, if you don't need it;
// otherwise be sure to use a parameter of type ActionEvent
@FXML
private void modify() throws IOException {
myData data = valueTable.getSelectionModel().getSelectedItem();
if (data != null) {
FXMLLoader loader = new FXMLLoader(getClass().getResource("modify.fxml"));
Parent root = loader.load();
ModifyController mpc = loader.getController();
mpc.setData(data);
Stage modifyStage = new Stage();
Scene modfifyPartScene = new Scene(root);
modifyStage.setScene(modfifyPartScene);
modifyStage.showAndWait();
if (mpc.isEdited()) {
valueTable.refresh(); // or update the table by other means
}
}
}
}
public class ModifyController {
@FXML
private TextField valueTxtFld;
@FXML
private Button mdfSaveBtn;
private myData data;
// flag indicating, if the edit was submitted or not
private boolean edited;
public boolean isEdited() {
return edited;
}
public void setData(myData selectedItem) {
if (selectedItem == null) {
throw new IllegalArgumentException();
}
this.data = selectedItem;
valueTxtFld.setText(selectedItem.getValue());
edited = false;
}
public void save() {
data.setValue(valueTxtFld.getText());
edited = true;
mdfSaveBtn.getScene().getWindow().hide();
}
}
关于JavaFX:如何在新场景中更新 observableArrayList 中选定的项目。没有传递整组数据支持吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55701298/
我是一名优秀的程序员,十分优秀!