JavaFX canvas has a lot of objects (<250.000 => 500x500 pixels)

This is my first question for Stackoverflow, so be gentle with me :)

I recently discovered JavaFX as a new approach to developing a GUI for Java applications. I am currently working on a project that requires the creation of up to 500x500 (250,000) objects on Canvas, which can be from 1x1px to 20x20px large (all have the same size). Unfortunately, the performance is not very good. Drawing a 500x500 rectangle field takes 10 seconds. I made an example application to demonstrate the problem.

Why is performance so bad? Because the drawing takes place in the user interface stream, the user interface is blocked until the drawing is completed. I have 2 questions:

  • Make the drawing quick.
  • Draw a buffer object in a separate thread and show the result on the canvas.

My experiments with writing to BufferedImage before drawing this image on the canvas were very unsuccessful (the canvas remained empty).

Thanks for taking the time to help research this topic :)

sample.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.GridPane?>

<AnchorPane prefHeight="275.0" prefWidth="300.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/2.2" fx:controller="sample.Controller">
  <children>
    <ScrollPane fx:id="scrollPane" content="$null" prefHeight="237.0" prefWidth="300.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="38.0" />
    <Button layoutX="14.0" layoutY="14.0" mnemonicParsing="false" onAction="#draw" text="Draw" />
  </children>
</AnchorPane>

Controller.java:

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.ScrollPane;
import javafx.scene.paint.Color;

import java.util.Random;

public class Controller {

    @FXML
    private ScrollPane scrollPane;

    Canvas canvas;
    @FXML
    protected void draw(ActionEvent event) {
    canvas = new Canvas(500,500);
    scrollPane.setContent(canvas);
    GraphicsContext gc = canvas.getGraphicsContext2D();
        Random r = new Random();

        for(int i = 0; i<=500; i++) {
            for(int j = 0; j<=500; j++) {
                if (r.nextBoolean()) {
                    gc.setFill(Color.BLACK);
                } else {
                    gc.setFill(Color.BLUE);
                }
                gc.fillRect(i, j, i+1, j+1);
            }
        }
    }
}

Main.java:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        ScrollPane scrollPane = (ScrollPane) root.lookup("#scrollPane");
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}
+4
source share
1 answer

, canvas . , . :

protected void draw(...) { canvas = new Canvas(...); }

.

public void start(...) { ... /* Other initialization. */ ... ; canvas = new Canvas(...); }

.

1: , , Google .

2: , , , . Java . , . , someCanvas.getGraphicsConfiguration() + .getBufferCapabilities() + .isPageFlipping().

+4

All Articles