0

I'm trying to update my JavaFX GUI after every 1 second using Task concuurency. I've icons 1.png, 2.png, 3.png and so on. I'm using a while loop increments i++. I want to display those icons after every 1 second. I don't know how to update Image. I'm using label.setGraphic() method. I don't know how to use bind property here. I may be stark wrong. Please help me.

@Override
public void start() {
  ...
  image = new Image(getClass().getResourceAsStream("images/1.png"));
  imv=new ImageView(image);
  label1 = new Label();
  label1.setGraphic(imv);
  monitor(); //A SEPARATE METHOD CONTAINING TASK CODE
  ...
  new Thread(task1).start();
}

...
public void monitor() {
  task1=new Task<Void>() {
    @Override
    protected Void call() {
      int i=1;
      while(true) {
        try {
          Thread.sleep(1000);
          updateMessage(""+i+".png");
          System.out.println("i: "+i);
        }
        catch(Exception e) {
        }
        i++;
        }
     }
  };
  label1.textProperty().bind(task1.messageProperty());
  ...
}
Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
Robert
  • 3
  • 3
  • Can you please share a [minimal, complete and verifiable example](https://stackoverflow.com/help/mcve) so we can reproduce your problem? – Samuel Philipp Mar 10 '19 at 15:01
  • 1
    Sure. I've uploaded to a repo. Read description also. https://github.com/tmtanzeel/image-slideshow – Robert Mar 10 '19 at 15:58
  • The code in GitHub differs a bit from that showed in your question: `new Thread(task1).start();` which is `new Thread(task).start();` on GitHub and `label1.textProperty().bind(task1.messageProperty());` which is `imv.imageProperty().bind(task1.messageProperty());` on GitHub. – Samuel Philipp Mar 10 '19 at 16:12
  • Please consider the code given on github. The code above was edited later on as I was trying different different approaches. – Robert Mar 10 '19 at 16:17
  • Then please update the code in your question to match the code in your question. – Samuel Philipp Mar 10 '19 at 16:18
  • You should probably look into `Timeline`. https://stackoverflow.com/questions/9966136/javafx-periodic-background-task – SedJ601 Mar 10 '19 at 17:58

1 Answers1

0

The error is that you can not bind a ReadOnlyStringProperty to an ObjectProperty<Image>.

You should add a change listener (docs) to the task message property (docs) and create an image which you then apply to your image view:

public void monitor() {
    task1 = new Task<Void>() {
        @Override
        protected Void call() {
            System.out.println("run called");
            int i = 1;
            while (true) {
                try {
                    Thread.sleep(1000);
                    updateMessage(i + ".png");
                    System.out.println("i: " + i);
                } catch (Exception e) {

                }
                i++;
            }
        }
    };
    task1.messageProperty().addListener((observable, oldValue, newValue) -> {
        System.out.println(newValue);
        Image image = new Image(getClass().getResourceAsStream("images/" + newValue));
        imv.setImage(image);
    });
}

EDIT:

The ChangeListener is represented by that Lambda expression in the given snippet. Please read the provided docs for more information.

Samuel Philipp
  • 10,631
  • 12
  • 36
  • 56
  • According to your code on GitHub you also have to change `new Thread(task).start();` to `new Thread(task1).start();` – Samuel Philipp Mar 10 '19 at 16:20
  • I'm sorry i'm not understanding things very clearly. Can you please make changes to the github program and give me a working version. Thanks in advance. – Robert Mar 10 '19 at 16:24
  • Also i'm pretty new to Javafx. – Robert Mar 10 '19 at 16:25
  • Just replace the line `imv.imageProperty().bind(task1.messageProperty());` with the snippet I shared in my answer. – Samuel Philipp Mar 10 '19 at 16:28
  • Replaced. Done. – Robert Mar 10 '19 at 16:29
  • Eclipse says: The method bind(ObservableValue extends Image>) in the type Property is not applicable for the arguments (ReadOnlyStringProperty) – Robert Mar 10 '19 at 16:31
  • Yes that's the issue I was talking about in my answer. – Samuel Philipp Mar 10 '19 at 16:33
  • Yes. But I'm not able to figure out what observable, oldValue and newValue are. – Robert Mar 10 '19 at 16:37
  • public void monitor() { task1=new Task() { @Override protected Void call() { System.out.println("run called"); int i=1; while(true) { try { Thread.sleep(1000); task1.messageProperty().addListener((observable, oldValue, newValue) -> { System.out.println(newValue); Image image = new Image(getClass().getResourceAsStream("images/" + i+".png")); imv.setImage(image); }); } catch(Exception e) { } i++; } } }; } – Robert Mar 10 '19 at 16:37
  • Please provide a working program.Its a humble request. I've already wasted 4 days with this. You can share your code on github. – Robert Mar 10 '19 at 16:39
  • I updated my answer and referred some docs and extended the code. SO is not a Platform for tasks like "write my code please". – Samuel Philipp Mar 10 '19 at 16:52
  • I've made all the changes you suggested in the guthib code. But it not displaying anything. Just a blank scene/stage. – Robert Mar 10 '19 at 18:10
  • The `monitor()` method i shared in my answer does not match the `monitor()` method you currently pushed on GitHub. – Samuel Philipp Mar 10 '19 at 18:13
  • made changes. now its exactly the way you told. but now i'm getting exceptions. run called i: 1 1.png Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at Main.lambda$0(Main.java:70)...so on for each iteration – Robert Mar 10 '19 at 18:19
  • You screwed up the initialization of your `ImageView imv;` its null, because you didn't initialize it. – Samuel Philipp Mar 10 '19 at 18:25
  • Wow. that solved the exceptions. Initialized ImageView on line 70. Added imv=new ImageView(); But still no image is displayed. I'm almost there. A little more help please. Console output seems to be perfect. – Robert Mar 10 '19 at 18:30
  • You should just revert to the first version. Initialize the ImageView in the `start()` method, so the label has the imageView as graphic and not null. – Samuel Philipp Mar 10 '19 at 18:33
  • Wow..It is working now. As perfectly as i wanted it to be. You have no idea how much thankful i am. I'll remember you all my life. I will mention you in project acknowledgemnt. :-) – Robert Mar 10 '19 at 18:38
  • I've also committed final bug free code on github on the same repo. Thanks a lot man. I've spent 100+ hours on this. Can have some beer now. – Robert Mar 10 '19 at 18:42