JavaFX: изменение размера холста не работает должным образом - PullRequest
0 голосов
/ 06 марта 2020

У меня есть приложение JavaFX, где есть холст с фиолетовым фоном и 2 диагональными линиями. Я связал размеры холста с соответствующим контейнером панели. Каждый раз, когда размер этого холста изменяется, я перерисовываю его.

Следуйте коду:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.time.LocalTime;

public class TestPaintColor0 extends Application {

    private void printChange(ReadOnlyProperty<Number> observable, Number oldValue, Number newValue, Canvas canvas) {
        System.out.printf("[%s] %10s.%-10s: %4.0f -> %4.0f. Canvas: %4.0f x %4.0f.\n",
                LocalTime.now(), observable.getBean().getClass().getSimpleName(), observable.getName(), oldValue, newValue,
                canvas.getWidth(), canvas.getHeight());
    }

    private void repaint(ObservableValue<? extends Number> observable, Number oldValue, Number newValue, Canvas canvas) {
        GraphicsContext gc = canvas.getGraphicsContext2D();

        // Should clear canvas.
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());

        // Paint background
        gc.setFill(Color.PURPLE);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

        // draw diagonals
        gc.setStroke(Color.BLACK);
        gc.moveTo(0, 0);
        gc.lineTo(canvas.getWidth(), canvas.getHeight());
        gc.moveTo(0, canvas.getHeight());
        gc.lineTo(canvas.getWidth(), 0);
        gc.stroke();

        printChange((ReadOnlyProperty<Number>) observable, oldValue, newValue, canvas);
    }

    @Override
    public void start(Stage primaryStage) {
        final Canvas canvas = new Canvas();
//        final Canvas canvas = new Canvas() {
//            @Override
//            public boolean isResizable() {
//                return true;
//            }
//        };
        canvas.heightProperty().addListener((observable, oldValue, newValue) -> repaint(observable, oldValue, newValue, canvas));
        canvas.widthProperty().addListener((observable, oldValue, newValue) -> repaint(observable, oldValue, newValue, canvas));

        FlowPane pane = new FlowPane(canvas);
        pane.setPadding(new Insets(5));
        canvas.widthProperty().bind(pane.widthProperty());
        canvas.heightProperty().bind(pane.heightProperty());
        pane.heightProperty().addListener((observable, oldValue, newValue) ->
                printChange((ReadOnlyDoubleProperty) observable, oldValue, newValue, canvas));
        pane.widthProperty().addListener((observable, oldValue, newValue) ->
                printChange((ReadOnlyDoubleProperty) observable, oldValue, newValue, canvas));

        primaryStage.setScene(new Scene(pane, 600, 400));
        primaryStage.titleProperty().bind(
                Bindings.concat(
                        "Test paint Pixel. Canvas: ", pane.widthProperty().asString(), " x ", pane.heightProperty().asString()
                )
        );
        primaryStage.show();
    }

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

}

Ниже приложения, когда оно запускается.

Application when launched

Вот что происходит, когда я изменяю размер приложения:

Application after resized

Как видите, холст не перерисованы. Вместо этого линии накладываются. Даже после вызова GraphicsContext.clearRect(), как предлагается во многих сообщениях здесь, в StackOverflow. Кроме того, если вы видите изображение кулака, заполнение панели не работает. На самом деле, видимо, работают только верхний и левый отступы, но не нижний и правый. Между нижним и правым холстом и приложением нет места windows.

Так кто-нибудь имеет представление о том, что здесь не так?

Спасибо,

1 Ответ

0 голосов
/ 06 марта 2020

Основываясь на предложениях @fabian, я смог решить как проблему очистки холста, так и его размер. Хотя настройка размера - это обходной путь, используя вставки панели.:

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.ReadOnlyProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.FlowPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.time.LocalTime;

public class TestPaintColor0 extends Application {

    private void printChange(ReadOnlyProperty<Number> observable, Number oldValue, Number newValue, Canvas canvas) {
        System.out.printf("[%s] %10s.%-10s: %4.0f -> %4.0f. Canvas: %4.0f x %4.0f.\n",
                LocalTime.now(), observable.getBean().getClass().getSimpleName(), observable.getName(), oldValue, newValue,
                canvas.getWidth(), canvas.getHeight());
    }

    private void repaint(ObservableValue<? extends Number> observable, Number oldValue, Number newValue, Canvas canvas) {
        GraphicsContext gc = canvas.getGraphicsContext2D();

        // Should clear canvas.
        gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        // SOLUTION TO CLEAN CANVAS
        gc.beginPath();

        // Paint background
        gc.setFill(Color.PURPLE);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

        // draw diagonals
        gc.setStroke(Color.BLACK);
        gc.moveTo(0, 0);
        gc.lineTo(canvas.getWidth(), canvas.getHeight());
        gc.moveTo(0, canvas.getHeight());
        gc.lineTo(canvas.getWidth(), 0);
        gc.stroke();

        printChange((ReadOnlyProperty<Number>) observable, oldValue, newValue, canvas);
    }

    @Override
    public void start(Stage primaryStage) {
        final Canvas canvas = new Canvas();
        canvas.heightProperty().addListener((observable, oldValue, newValue) -> repaint(observable, oldValue, newValue, canvas));
        canvas.widthProperty().addListener((observable, oldValue, newValue) -> repaint(observable, oldValue, newValue, canvas));

        FlowPane pane = new FlowPane(canvas);

        pane.setPadding(new Insets(5));

        // WORKAROUND TO RESIZE CANVAS!!!! - BEGIN!
        canvas.widthProperty().bind(pane.widthProperty().subtract(pane.getInsets().getLeft() + pane.getInsets().getRight()));
        canvas.heightProperty().bind(pane.heightProperty().subtract(pane.getInsets().getTop() + pane.getInsets().getBottom()));
        // WORKAROUND TO RESIZE CANVAS!!!! - END!

        pane.heightProperty().addListener((observable, oldValue, newValue) ->
                printChange((ReadOnlyDoubleProperty) observable, oldValue, newValue, canvas));
        pane.widthProperty().addListener((observable, oldValue, newValue) ->
                printChange((ReadOnlyDoubleProperty) observable, oldValue, newValue, canvas));

        primaryStage.setScene(new Scene(pane, 600, 400));
        primaryStage.titleProperty().bind(
                Bindings.concat(
                        "Test paint Pixel. Canvas: ", pane.widthProperty().asString(), " x ", pane.heightProperty().asString()
                )
        );
        primaryStage.show();
    }

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...