2

In PySide you can override the paintEvent() method of a QWidget to control how the widget is painted on the screen. Is there an equivalent for Node in JavaFX?


In context: I'm in need of a way to display a custom image format on the screen. Constantly converting my format and JavaFX's Image so I can display it in an ImageView is too slow for me, in addition to being messier.

I've taken a look at ImageView.java and Canvas.java, but no luck. ImageView is using css, and Canvas appears to be doing something with the deprecated impl_ methods, for which I've found no documentation on.

Thanks!

midrare
  • 2,371
  • 28
  • 48
  • 1
    I'm not sure what you mean by "`ImageView` is using css". You can either use a [`WritableImage`](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/WritableImage.html) as the image provided to an `ImageView`, or use a [`Canvas`](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/Canvas.html) and its [`GraphicsContext`](http://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/GraphicsContext.html). The `GraphicsContext` has plenty of public API for drawing the image. – James_D Jun 12 '14 at 13:53
  • 1
    What is the image format? – Mansueli Jun 12 '14 at 18:19
  • @James_D @Kyllopardiun I didn't read too deep into it, but it appears `ImageView` displays its image by styling itself with the `-fx-image` CSS property, but the actual painting is done elsewhere. It might be in one of the `impl_` methods, but without docs I can't make sense of them. I have an array of `int`s representing the image data. It's an image editor I'm working on; the speed at which I can update the image view to reflect changes to the image data is an issue here, which is why I don't want to be converting between two formats all the time. – midrare Jun 12 '14 at 22:58
  • I don't understand sorbet, discussion of CSS and `impl_` methods seems irrelevant. If you have an array ints which is a buffer representing the image data, why can't you use a WritableImage as James_D suggests (`writableImage.getPixelWriter().setPixels(...)`)? – jewelsea Jun 23 '16 at 18:34

1 Answers1

2

Generally, the paint mechanisms in JavaFX changed towards a more event-based approach. To follow the JavaFX way, you should probably look at Timeline or AnimationTimer and only update the display when the actual image data changes.

However, you could use the old Swing way in JavaFX, if you like:

public class MyPane extends Pane {
    private final Canvas canvas;

    public MyPane() {
        canvas = new Canvas(getWidth(), getHeight());
        getChildren().add(canvas);
        widthProperty().addListener(e -> canvas.setWidth(getWidth()));
        heightProperty().addListener(e -> canvas.setHeight(getHeight()));
    }

    @Override
    protected void layoutChildren() {
        super.layoutChildren();

        GraphicsContext gc = canvas.getGraphicsContext2D();

        gc.clearRect(0, 0, getWidth(), getHeight());

        gc.setFill(Color.RED);
        gc.fillRect(10, 10, getWidth() - 20, getHeight() - 20);

        // Paint your custom image here:
        gc.drawImage(someImage, 0, 0);
    }
}

The above code would be the equivalence of this Swing code:

public class MyPanel extends JPanel {
    private static final long serialVersionUID = -969772195113348076L;

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.clearRect(0, 0, getWidth(), getHeight());

        g.setColor(java.awt.Color.RED);
        g.fillRect(10, 10, getWidth() - 20, getHeight() - 20);

        // Paint your custom image here:
        g.drawImage(someImage, 0, 0, null);
    }
}
user3151902
  • 3,154
  • 1
  • 19
  • 32