簡體   English   中英

從另一個類調用控制器方法后,JavaFX FXML無法更新

[英]JavaFX FXML doesn't get updated after calling controller method from another class

這個問題困擾了我幾個小時。 它沒有給我任何例外,控制台得到了更新,這告訴我該方法正在執行,但ui不變。 這是我的課程:

控制器類:

public class Controller {

public HBox billbox;

public int childnr;

public void createBill(){
    System.out.println("Creating");
    TableView<Item> bill = new TableView<>();

    DropShadow dropShadow = new DropShadow();
    dropShadow.setRadius(5.0);
    dropShadow.setOffsetX(3.0);
    dropShadow.setOffsetY(3.0);
    dropShadow.setColor(Color.color(0.4, 0.5, 0.5));

    VBox fullbill = new VBox();
    fullbill.setPadding(new Insets(1,1,1,1));
    fullbill.getStyleClass().add("fullbill");

    TableColumn<Item,String> nameColumn = new TableColumn<>("Emri");
    nameColumn.setMinWidth(200);
    nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));

    TableColumn<Item,String> quantsColumn = new TableColumn<>("Sasia");
    quantsColumn.setMinWidth(50);
    quantsColumn.setCellValueFactory(new PropertyValueFactory<>("quants"));

    double tablewidth = nameColumn.getWidth() + quantsColumn.getWidth();

    Label tablenrlabel = new Label("Table 5");
    tablenrlabel.getStyleClass().add("tablenr-label");
    tablenrlabel.setMinWidth(tablewidth);

    Button closebutton = new Button("Mbyll");
    closebutton.setMinWidth(tablewidth);
    closebutton.getStyleClass().add("red-tint");

    bill.setItems(getItem());
    bill.setMinWidth(256);
    bill.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
    bill.getColumns().addAll(nameColumn,quantsColumn);

    fullbill.setEffect(dropShadow);
    fullbill.getChildren().addAll(tablenrlabel,bill,closebutton);

    billbox.getChildren().addAll(fullbill);

    childnr += 1;

    //Loops over every button in every vbox and gives it a seperate listener (the index of the button is hardcoded so it can cause problems if you add more items)
    for(int i = 0; i < childnr; i++){
        VBox box = (VBox) billbox.getChildren().get(i);
        Button btn = (Button) box.getChildren().get(2); //if sudden issues change this
        btn.setId(Integer.valueOf(i).toString());
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                int index = billbox.getChildren().indexOf(btn.getParent());
                billbox.getChildren().remove(index);
                childnr -= 1;
                System.out.println(btn.getId());
            }
        });
    }
    System.out.println("done");
}


public ObservableList<Item> getItem(){
    ObservableList<Item> items = FXCollections.observableArrayList();
    items.add(new Item("Fanta",1));
    items.add(new Item("Kafe",1));
    items.add(new Item("Schweps",1));

    return items;
}

調用控制器createBill()方法的類:

public void run(){

    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            try {

                URL location = getClass().getResource("sample.fxml");
                FXMLLoader fxmlLoader = new FXMLLoader();
                fxmlLoader.setLocation(location);
                fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());

                Parent root = (Parent) fxmlLoader.load(location.openStream());
                Controller controller = fxmlLoader.<Controller>getController();
                root.setUserData(controller);
                controller.createBill();
            }catch (Exception x){
                System.out.println(x);
            }
        }
    });

}

這是我的主要方法:

public class Main extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception{

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("uPick Smart Service");
        primaryStage.setScene(new Scene(root, 1600, 600));

        primaryStage.show();


    }

    public static void main(String args[]){
        launch(args);

    }
}

FXMLLoader.load()加載FXML文件並FXMLLoader.load()創建對象層次結構:即,它創建一個與根元素中指定的類相對應的新對象,並在其上設置屬性(通常設置這些屬性涉及創建其他對象,等等)。 FXMLLoader (通常)創建的控制器與該特定對象層次結構關聯。

run()方法中,您加載了FXML文件,並檢索了關聯的控制器,但實際上從未顯示過FXML文件定義的UI:

URL location = getClass().getResource("sample.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(location);
fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());

// Loads the FXML file and creates a bunch of objects,
// but you never display the result: you do nothing with root:
Parent root = (Parent) fxmlLoader.load(location.openStream());

// retrieve the controller associate with root:
Controller controller = fxmlLoader.<Controller>getController();
// not sure what this is for...
root.setUserData(controller);
// now call a method on the controller.
controller.createBill();

調用controller.createBill() ,它會修改與控制器關聯的UI元素,因此會修改root及其子元素。 但是,由於root永遠不會顯示在任何地方,因此您永遠不會看到結果。

請注意,您加載了相同的FXML文件兩次,因此,它具有定義的UI的兩個副本以及控制器類的兩個實例。 控制器的每個實例都與UI的一個實例相關聯。 通過在start()方法中加載FXML文件而獲得的UI就是顯示的UI。 因此,要修改UI的外觀,您需要在由您在FXMLLoader創建的FXMLLoader創建的控制器實例上調用方法,而不是在其他FXMLLoader上調用方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM