在JavaFX 8中绘制滚动窗格内部

时间:2014-10-06 18:26:30

标签: canvas javafx drawing scrollpane

经过几个小时的搜索,我无法找到解决问题的方法。

我有一个简单的绘图应用程序,我有一个矩形来绘制线条。这个矩形应该在Scrollpane中,所以如果它是'大于程序窗口,用户只需滚动到不同的位置。

这是我目前的做法:

    /**
     * @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);

...

        // Build the canvas
        canvas.setCursor(Cursor.CROSSHAIR);
        canvas.setFill(Color.LIGHTGRAY);
        canvas.setOnMousePressed(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent me) {

                path = new Path();
                path.setMouseTransparent(true);
                path.setStrokeWidth(sampleLine.getStrokeWidth());
                path.setStroke(sampleLine.getStroke());
                line_Group.getChildren().add(path);
                path.getElements().add(new MoveTo(me.getSceneX(), me.getSceneY()));
            }
        });


        canvas.setOnMouseDragged(new EventHandler<MouseEvent>() {

            @Override
            public void handle(MouseEvent me) {

                // keep lines within rectangle

                if (canvas.getBoundsInLocal().contains(me.getX(), me.getY())) {
                path.getElements().add(new LineTo(me.getSceneX(), me.getSceneY()));
                }

            }
        });


        // Build the VBox container for the toolBox, sampleline, and canvas
        final Group board  = new Group();
        board.getChildren().addAll(canvas, line_Group);
        ScrollPane scroll = createScrollPane(board);

        VBox vb = new VBox(20);
        vb.setPrefWidth(scene.getWidth() - 20);
        vb.setLayoutY(20);
        vb.setLayoutX(10);
        vb.getChildren().addAll(toolBox, stackpane, scroll);
        root.getChildren().addAll(vb);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

...

    private ScrollPane createScrollPane(Group layout) {
        ScrollPane scroll = new ScrollPane();
        scroll.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
        scroll.setMaxHeight(400);
        scroll.setContent(layout);
        return scroll;
    }
}

这里的问题是,绘制的路径总是在相同的位置绘制,即如果我移动滚动条进一步向下绘制,它不会改变任何东西。

我尝试过使用&#34; .getX()&#34;而不是&#34; .getsceneX()&#34;在mouseEvent中,但这并没有帮助。

我是JavaFX的新手所以请耐心等待我

1 个答案:

答案 0 :(得分:2)

这是一个简单的应用程序,但有些事情会根据具体要求而改变,例如:如果用户拖动滚动窗格外会发生什么?绘图区域是固定的还是大小至少是可视区域的最小尺寸?等等。

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

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

lines in scrollpane

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();
    }
}