gpt4 book ai didi

JavaFX:如何在新场景中更新 observableArrayList 中选定的项目。没有传递整组数据支持吗?

转载 作者:行者123 更新时间:2023-11-30 01:52:07 28 4
gpt4 key购买 nike

JavaFX:如何在新场景中更新 observableArrayList 中选定的项目。没有传递整组数据支持吗?

我认为将一个选定的项目传递到新窗口是有意义的。我无法通过这样做让 observableArrayList 反射(reflect)更改。

我只能通过传递整个数据集来让我的程序运行。支持 observableArrayList 的 ArrayList 和 observableArrayList 本身。然后在ArrayList中查找元素,修改该元素,将元素重新插入到列表中,然后清除整个ArrayList并将其重新添加到observableArrayList中。我确信这不是最好的方法。作为 Javafx 的新手,我不确定如何进行这项工作。

这是我如何完成此工作的一个工作示例。希望这能凸显出我做错了什么以及我需要改变什么。

请注意:如果可能的话,我不想使用任何静态类。这是一个小项目,我计划扩展到更大的项目,并且我想避免使用静态类的陷阱。

请注意:我省略了过帐导入。假设我有正确的导入。

示例代码的视觉引用 Visual example of my working example,

目录结构。

    --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();


}
}

ma​​in.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:您可以传递不同的 TextFieldgetValueTxtFld 返回到 setValueTxtFld 导致的错误不是最简单的调试错误。如果您只是提供对正在使用的属性(TextField.text 属性)的访问权限,那么这不会成为问题。但在这种情况下,不需要访问权限。
  • 迭代列表时不要修改列表。您可能会收到 ConcurrentModificationException。也不要用比较哈希码来代替检查相等性。这比必要的更复杂并且可能会失败。 (假设您的 hashCode 实现仅基于 String 值,则每个可能的 int 都有一个字符串,并且有些字符串不包含int 值,因此必须有 2 个不同的对象具有相同的哈希码)。
    只需使用 indexOf 即可:

    int index = values.indexOf(data);
    values.set(index, ...);
<小时/>

ma​​in.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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com