简体   繁体   English

JavaFX ImageView 未更新

[英]JavaFX ImageView not updating

So I'm trying to load and save Images into an imageView where the location of the image is chosen through a file browser.所以我试图将图像加载并保存到 imageView 中,其中通过文件浏览器选择图像的位置。 I've been working on this for several days now and I'm gonna have a stroke if I can't get it fixed.我已经为此工作了好几天了,如果我不能把它修好,我就会中风。 I've tried everything I can think of.我已经尝试了所有我能想到的。 Thank you in advance for helping.预先感谢您的帮助。

UPDATED :更新

Here is my main class:这是我的主要课程:

public class Main extends Application {
    private Stage primaryStage;
    private BorderPane rootLayout;
    public Main(){}
    @Override
    public void start(Stage primaryStage) throws Exception{
      this.primaryStage = primaryStage;
      this.primaryStage.setTitle("Help Please");
      initRootLayout();
      showScreen();
    }
    public void initRootLayout(){
        try{
            FXMLLoader loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
            rootLayout = (BorderPane) loader.load();
            Scene scene = new Scene(rootLayout);
            primaryStage.setScene(scene);
            RootLayout controller = loader.getController();
            controller.setMain(this);
            primaryStage.show();
        }catch(Exception e ){e.printStackTrace();}
    }
    public void showScreen(){
        try{FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("view/sample.fxml"));
        BorderPane sample = (BorderPane)loader.load();
        rootLayout.setCenter(sample);
        Controller controller = loader.getController();
        controller.setMain(this);
        }catch (Exception e){e.printStackTrace();}
    }
    public Stage getPrimaryStage(){return primaryStage;}
    public static void main(String[] args) {
        launch(args);
    }
}

Here is the rootLayout:这是根布局:

public class RootLayout {
    private Main main;
    private Controller controller = new Controller();
    public void setMain(Main main){this.main = main;}
    @FXML
    private void handleOpen(){
        FileChooser fileChooser = new FileChooser();
        FileChooser.ExtensionFilter extensionFilter = new FileChooser.ExtensionFilter(
                "PNG files (*.png)","*png");
        fileChooser.getExtensionFilters().add(extensionFilter);
        File file = fileChooser.showOpenDialog(main.getPrimaryStage());
        if(file!= null){
            controller.updateImage(file.toURI().toString());
        }
    }
}

And here is the controller:这是控制器:

public class Controller implements Initializable {
    @FXML
    ImageView imageView = new ImageView();
    String imageURL;
    Main main = new Main();
    public void setMain(Main main){
        this.main = main;
    }
    public void updateImage(String url){
        if(url.length()>=1){
            Image image = new Image(url);
            imageView.setImage(image);
            System.out.println(url);
        }
        else{
            System.out.println(url);
            System.out.println("image invalid");
        }
    }
    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }
}

Two things:两件事情:

  1. Never assign a field whose value is to be injected by an FXMLLoader (eg @FXML fields).切勿分配其值将由FXMLLoader注入的FXMLLoader (例如@FXML字段)。 Doing so is a waste of resources at best and introduces subtle bugs at worst.这样做充其量是浪费资源,最糟糕的是会引入微妙的错误。 For instance, if you were to leave the imageView field uninitialized you'd be getting a NullPointerException which would indicate a problem with your setup.例如,如果您未初始化imageView字段,则会收到NullPointerException ,这表明您的设置存在问题。 Since you do initialize the field, however, you don't get any errors and there's a false impression of the code working.但是,由于您确实初始化了该字段,因此您不会收到任何错误,并且对代码工作有一种错误的印象。

  2. In your RootLayout controller class, you have:在您的RootLayout控制器类中,您有:

     private Controller controller = new Controller();

    That instance of Controller you just created is not linked to any FXML file.您刚刚创建的那个Controller实例没有链接到任何 FXML 文件。 And since you initialize the imageView field (see first point) you end up updating an ImageView which is not being displayed anywhere;并且由于您初始化了imageView字段(请参阅第一点),因此您最终会更新未在任何地方显示的ImageView this is where not initializing said field would have given a nice indication of there being a problem.这是不初始化所述字段会很好地表明存在问题的地方。 The solution is to pass the Controller instance created by the FXMLLoader to the RootLayout instance created by the other FXMLLoader .解决方案是将FXMLLoader创建的Controller实例FXMLLoader给另一个FXMLLoader创建的RootLayout实例。

    Also, in the same class you have:此外,在同一个班级中,您有:

     Main main = new Main();

    Which is also unnecessary since the created instance of Main is both not the correct instance and is replaced by the call to #setMain(Main) almost immediately.这也是不必要的,因为创建的Main实例既不是正确的实例,又几乎立即被调用#setMain(Main)替换。


Assuming your FXML files (which you did not provide) are correct, the Java classes should look more like:假设您的 FXML 文件(您没有提供)是正确的,Java 类应该看起来更像:

Main.java主程序

public class Main extends Application {

  private Stage primaryStage;
  private BorderPane rootLayout;
  private RootLayout rootLayoutController;

  public Main() {}

  @Override
  public void start(Stage primaryStage) throws Exception {
    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("Help Please");
    initRootLayout();
    showScreen();
  }

  public void initRootLayout() {
    try {
      FXMLLoader loader = new FXMLLoader();
      loader.setLocation(Main.class.getResource("view/RootLayout.fxml"));
      rootLayout = (BorderPane) loader.load();
      Scene scene = new Scene(rootLayout);
      primaryStage.setScene(scene);

      // store RootLayout instance in field so #showScreen()
      // can reference it
      rootLayoutController = loader.getController();
      rootLayoutController.setMain(this);

      primaryStage.show();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void showScreen() {
    try {
      FXMLLoader loader = new FXMLLoader();
      loader.setLocation(Main.class.getResource("view/sample.fxml"));
      BorderPane sample = (BorderPane) loader.load();
      rootLayout.setCenter(sample);
      Controller controller = loader.getController();
      controller.setMain(this);

      // set Controller instance on RootLayout instance
      rootLayoutController.setController(controller);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public Stage getPrimaryStage() {
    return primaryStage;
  }

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

RootLayout.java根布局.java

public class RootLayout {

  private Main main;
  private Controller controller;

  public void setMain(Main main) {
    this.main = main;
  }

  public void setController(Controller controller) {
    this.controller = controller;
  }

  @FXML
  private void handleOpen() {
    FileChooser fileChooser = new FileChooser();
    // Note extensions should be prefixed with "*."
    FileChooser.ExtensionFilter extensionFilter =
        new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");
    fileChooser.getExtensionFilters().add(extensionFilter);
    File file = fileChooser.showOpenDialog(main.getPrimaryStage());
    if (file != null) {
      controller.updateImage(file.toURI().toString());
    }
  }
}

Controller.java控制器.java

public class Controller implements Initializable {

  @FXML ImageView imageView; // leave uninitialized, will be injected
  String imageURL;
  Main main;

  public void setMain(Main main) {
    this.main = main;
  }

  public void updateImage(String url) {
    if (url.length() >= 1) {
      Image image = new Image(url);
      imageView.setImage(image);
      System.out.println(url);
    } else {
      System.out.println(url);
      System.out.println("image invalid");
    }
  }

  @Override
  public void initialize(URL location, ResourceBundle resources) {}
}

Note: Did not test new code.注意:没有测试新代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM