Canvas 在JavaFX8中的滚动窗格中绘制

Canvas 在JavaFX8中的滚动窗格中绘制,canvas,javafx,drawing,scrollpane,Canvas,Javafx,Drawing,Scrollpane,经过几个小时的搜索,我找不到解决问题的办法 我得到了一个简单的绘图应用程序,其中我有一个矩形来画线。这个矩形应该在滚动窗格中,这样如果它比程序窗口大,用户就可以滚动到不同的位置 以下是我目前的做法: /** * @param args the command line arguments */ public static void main(String[] args) { Application.launch(args); }

经过几个小时的搜索,我找不到解决问题的办法

我得到了一个简单的绘图应用程序,其中我有一个矩形来画线。这个矩形应该在滚动窗格中,这样如果它比程序窗口大,用户就可以滚动到不同的位置

以下是我目前的做法:

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Drawing Board Demo");
        final Group root = new Group();

        Scene scene = new Scene(root, 600, 800);

        // A group to hold all the drawn path elements
        line_Group = new Group();


        final Rectangle canvas = new Rectangle(scene.getWidth() - 20, scene.getHeight() - 20);

这里的问题是,绘制的路径始终绘制在同一位置,即如果我移动滚动条进一步向下绘制,它不会改变任何内容

我尝试在mouseEvent中使用“.getX()”而不是“.getsceneX()”,但也没有用


我是JavaFX新手,所以请耐心听我说,这是一个简单的应用程序,但有一些事情会根据具体要求而改变,例如,如果用户拖动到滚动窗格之外会发生什么?绘图区域是否固定,或其大小是否至少为可视区域的最小大小?等等

这是我提出的一个示例应用程序。它不会完全符合你的要求,因为我不知道它们到底是什么,但希望它能给你足够的基本信息,让你再次朝着正确的方向前进

按住并拖动鼠标在滚动窗格内显示的窗格上绘制线条。如果将窗格外部拖动到底部或右侧,绘图窗格的最小大小将更新以适应其中的新行内容。鼠标侦听器用于处理绘图操作的开始、设置端点和完成绘图操作

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class LineDrawer extends Application {

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

    private Line curLine;

    @Override
    public void start(Stage stage) throws Exception {
        Pane drawingPane = new Pane();
        drawingPane.setPrefSize(800, 800);
        drawingPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        ScrollPane scrollPane = new ScrollPane(drawingPane);
        scrollPane.setPrefSize(300, 300);
        scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        scrollPane.setFitToWidth(true);
        scrollPane.setFitToHeight(true);
        scrollPane.setStyle("-fx-focus-color: transparent;");

        drawingPane.setOnMousePressed(event -> {
            if (!event.isPrimaryButtonDown()) {
                return;
            }

            curLine = new Line(
                event.getX(), event.getY(), 
                event.getX(), event.getY()
            );
            drawingPane.getChildren().add(curLine);
        });

        drawingPane.setOnMouseDragged(event -> {
            if (!event.isPrimaryButtonDown()) {
                return;
            }

            if (curLine == null) {
                return;
            }

            curLine.setEndX(event.getX());
            curLine.setEndY(event.getY());

            double mx = Math.max(curLine.getStartX(), curLine.getEndX());
            double my = Math.max(curLine.getStartY(), curLine.getEndY());

            if (mx > drawingPane.getMinWidth()) {
                drawingPane.setMinWidth(mx);
            }

            if (my > drawingPane.getMinHeight()) {
                drawingPane.setMinHeight(my);
            }
        });

        drawingPane.setOnMouseReleased(event -> curLine = null);

        Scene scene = new Scene(scrollPane);
        stage.setMinWidth(100);
        stage.setMinHeight(100);
        stage.setScene(scene);
        stage.show();
    }
}


这是很多代码。是否可以将其精简一点(仅限于显示问题的代码),以便更容易帮助您?抱歉,我已删除了所有不影响此问题的代码。主要的问题是在“canvas.setonmousedrable”和createScrollPane“我想至少Hanks,这回答了我的问题。我只需要将“Line”替换为“Path”“形状。感谢您的帮助。这是一个很棒的演示,演示了一些通过搜索很难找到的关键概念。@jewelsea为什么要使用
窗格
而不是
画布
?在用户拖动时移动鼠标比使用窗格而不是画布更容易实现。我认为如果您尝试创建一个基于画布的解决方案,那么它最终会变得更加复杂。
    private ScrollPane createScrollPane(Group layout) {
        ScrollPane scroll = new ScrollPane();
        scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        scroll.setMaxHeight(400);
        scroll.setContent(layout);
        return scroll;
    }
}
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class LineDrawer extends Application {

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

    private Line curLine;

    @Override
    public void start(Stage stage) throws Exception {
        Pane drawingPane = new Pane();
        drawingPane.setPrefSize(800, 800);
        drawingPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        ScrollPane scrollPane = new ScrollPane(drawingPane);
        scrollPane.setPrefSize(300, 300);
        scrollPane.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        scrollPane.setFitToWidth(true);
        scrollPane.setFitToHeight(true);
        scrollPane.setStyle("-fx-focus-color: transparent;");

        drawingPane.setOnMousePressed(event -> {
            if (!event.isPrimaryButtonDown()) {
                return;
            }

            curLine = new Line(
                event.getX(), event.getY(), 
                event.getX(), event.getY()
            );
            drawingPane.getChildren().add(curLine);
        });

        drawingPane.setOnMouseDragged(event -> {
            if (!event.isPrimaryButtonDown()) {
                return;
            }

            if (curLine == null) {
                return;
            }

            curLine.setEndX(event.getX());
            curLine.setEndY(event.getY());

            double mx = Math.max(curLine.getStartX(), curLine.getEndX());
            double my = Math.max(curLine.getStartY(), curLine.getEndY());

            if (mx > drawingPane.getMinWidth()) {
                drawingPane.setMinWidth(mx);
            }

            if (my > drawingPane.getMinHeight()) {
                drawingPane.setMinHeight(my);
            }
        });

        drawingPane.setOnMouseReleased(event -> curLine = null);

        Scene scene = new Scene(scrollPane);
        stage.setMinWidth(100);
        stage.setMinHeight(100);
        stage.setScene(scene);
        stage.show();
    }
}