title: JavaFX Canvas Update
body: <p>I've been working on switching my applications from Swing to JavaFX. I've been working on a room escape game which displays a description of the item on which the user clicks. In Swing, I'd subclass <code>JComponent</code> and override the <code>paintComponent(Graphics)</code> method. I could draw the text there, knowing that the method is constantly called to update the screen. However, using the JavaFX Canvas, there is no method that is called constantly, which makes this task harder. I attempted <code>save()</code>ing the <code>GraphicsContext</code> after I drew the images and called <code>restore()</code> when I wanted to remove the text, but to no avail. Here's the important code:</p>
  
  <pre><code>package me.nrubin29.jescape;
  
  import javafx.application.Platform;
  import javafx.scene.canvas.Canvas;
  import javafx.scene.canvas.GraphicsContext;
  import javafx.scene.shape.Rectangle;
  
  import java.util.Timer;
  import java.util.TimerTask;
  
  public class RoomPane extends Canvas {
  
      private Room room;
  
      private Toast toast;
  
      public RoomPane() {
          super(640, 480);
  
          setOnMouseClicked(e -&gt; {
              for (JObject o : room.getObjects()) {
                  if (o.getBounds().contains(e.getX(), e.getY())) {
                      toast = new Toast(o.getDescription());
                  }
              }
          });
  
          new Timer().schedule(new TimerTask() {
              @Override
              public void run() {
                  if (toast == null) {
                      return;
                  }
  
                  if (toast.decrement()) { // Decrements the internal counter. If the count is 0, this method returns true.
                      toast = null;
                      Platform.runLater(() -&gt; getGraphicsContext2D().restore());
                  }
  
                  else {
                      Platform.runLater(() -&gt; getGraphicsContext2D().strokeText(toast.getText(), 300, 100));
                  }
              }
          }, 0, 1000);
      }
  
      public void changeRoom(Room room) {
          this.room = room;
  
          GraphicsContext g = getGraphicsContext2D();
  
          g.drawImage(room.getBackground(), 0, 0);
  
          for (JObject o : room.getObjects()) {
              g.drawImage(o.getImage(), getCenterX(o.getBounds()), getCenterY(o.getBounds()));
          }
  
          g.save();
      }
  }
  </code></pre>