如何在javaFX中制作canvas Resizable?

Hin*_*ara 11 javafx canvas javafx-2 fxml javafx-8

在javaFX中调整画布大小没有这样的方法,唯一的解决方案是从Canvas扩展.

class ResizableCanvas extends Canvas {

    public ResizableCanvas() {
        // Redraw canvas when size changes.
        widthProperty().addListener(evt -> draw());
        heightProperty().addListener(evt -> draw());
    }

    private void draw() {
        double width = getWidth();
        double height = getHeight();

        GraphicsContext gc = getGraphicsContext2D();
        gc.clearRect(0, 0, width, height);

    }

    @Override
    public boolean isResizable() {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

从Canvas扩展是唯一使画布Resizable的解决方案?因为这个解决方案只有在我们不想使用FXML时才有效,如果我们在fxml中声明一个画布,我们怎样才能使它可以调整大小?

这是我的代码:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Main extends Application {

    Controller controller;

    @Override
    public void start(Stage primaryStage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        AnchorPane root = loader.load(); // controller initialized
        controller = loader.getController();
        GraphicsContext gc = controller.canvas.getGraphicsContext2D();
        gc.setFill(Color.AQUA);
        gc.fillRect(0, 0, root.getPrefWidth(), root.getPrefHeight());
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(controller.Pane, controller.Pane.getPrefWidth(), controller.Pane.getPrefHeight()));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

sma*_*c89 7

在给出的所有答案中,在使画布与其父级自动调整大小方面,没有一个真正对我有用。我决定尝试一下,这就是我想出的:

import javafx.scene.canvas.Canvas;

public class ResizableCanvas extends Canvas {

    @Override
    public boolean isResizable() {
        return true;
    }

    @Override
    public double maxHeight(double width) {
        return Double.POSITIVE_INFINITY;
    }

    @Override
    public double maxWidth(double height) {
        return Double.POSITIVE_INFINITY;
    }

    @Override
    public double minWidth(double height) {
        return 1D;
    }

    @Override
    public double minHeight(double width) {
        return 1D;
    }

    @Override
    public void resize(double width, double height) {
        this.setWidth(width);
        this.setHeight(height);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是唯一真正使画布真正可调整大小的方法。


我采用这种方法的原因如下:

  • 我不想通过强制父组件在构造函数中向我们发送and来破坏封装,这也意味着画布不能在.widthheightFXML
  • 我也不想依赖父级widthheight属性,从而通过占用所有空间使画布成为其父级中唯一的子级。
  • 最后,画布需要在另一个类中完成绘制,这意味着我无法使用当前接受的答案,其中还包括通过 draw 方法绘制到画布。

使用这个画布,我不需要绑定到它的父宽度/高度属性来调整画布大小。它只是根据父级选择的大小调整大小。此外,任何使用画布的人都可以绑定到它的宽度/高度属性,并在这些属性发生变化时管理他们自己的绘图。


Mas*_*lor 5

有一个指南,我认为您可能会发现有用于设置可调整大小的画布:

JavaFx提示 - 可调整大小的画布

指南中的一段代码:

/**
 * Tip 1: A canvas resizing itself to the size of
 *        the parent pane.
 */
public class Tip1ResizableCanvas extends Application {

    class ResizableCanvas extends Canvas {

        public ResizableCanvas() {
            // Redraw canvas when size changes.
            widthProperty().addListener(evt -> draw());
            heightProperty().addListener(evt -> draw());
        }

        private void draw() {
            double width = getWidth();
            double height = getHeight();

            GraphicsContext gc = getGraphicsContext2D();
            gc.clearRect(0, 0, width, height);

            gc.setStroke(Color.RED);
            gc.strokeLine(0, 0, width, height);
            gc.strokeLine(0, height, width, 0);
        }

        @Override
        public boolean isResizable() {
            return true;
        }

        @Override
        public double prefWidth(double height) {
            return getWidth();
        }

        @Override
        public double prefHeight(double width) {
            return getHeight();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案缺少链接提示的重点:"将Canvas的宽度和高度属性绑定到父窗格的宽度和高度属性",例如,如果将画布添加到StackPane:canvas.widthProperty().bind( stackPane.widthProperty()); .canvas.heightProperty()结合(stackPane.heightProperty()); (2认同)

小智 5

取自http://werner.yellowcouch.org/log/resizable-javafx-canvas/:要使JavaFx Canvas可调整大小,所有需要做的就是覆盖min / pref / max方法。使其可调整大小并实现resize方法

使用此方法,不需要宽度/高度侦听器即可触发重绘。也不再需要将宽度和高度的大小绑定到容器。

public class ResizableCanvas extends Canvas {

@Override
public double minHeight(double width)
{
    return 64;
}

@Override
public double maxHeight(double width)
{
    return 1000;
}

@Override
public double prefHeight(double width)
{
    return minHeight(width);
}

@Override
public double minWidth(double height)
{
    return 0;
}

@Override
public double maxWidth(double height)
{
    return 10000;
}

@Override
public boolean isResizable()
{
    return true;
}

@Override
public void resize(double width, double height)
{
    super.setWidth(width);
    super.setHeight(height);
    <paint>
}
Run Code Online (Sandbox Code Playgroud)