缩放时画布上的绘图变得模糊

时间:2019-10-15 08:58:52

标签: java javafx zoom scale

这是另一个缩放问题,请先花点时间阅读。

我正在创建一个简单的绘画应用程序,需要在图像上绘制。当我放大/缩小绘图时,请留在其绘制的图像上。我正在使用ImageViewer显示图像,并使用Canvas显示图形。

首先要进行的操作是缩放和平移图像,例如您可以在Google Maps上进行的操作。现在,下一部分是在图像上绘制一些东西。由于我使用过ImageViewer,因此无法在其上绘画。因此,我添加了一个Canvas,可以在其中绘画。问题是,当我放大画布上的图纸时,它们会变得模糊和像素化。

在这种情况下,我可以使用javaSwing来解决此问题。

我尝试将相同的概念应用于我在Swing中的操作方式。就像在AffineTransform的{​​{1}}上应用graphics一样,但是在FX中不起作用。

我发现something也可以解决问题,但由于它使用了与我的矛盾的不同缩放算法,因此我似乎无法应用于我的项目。

我认为一些代码会有所帮助。

基于@jewelsea的答案的控制器类。

Jpanel

主类。

public class Controller implements Initializable {

    final double SCALE_DELTA = 1.1;
    final ObjectProperty<Point2D> lastMouseCoordinates = new SimpleObjectProperty<Point2D>();
    public ScrollPane scroller;
    public Group scrollContent;
    public StackPane zoomPane;
    public Group group;
    public ImageView imageView;
    public Canvas canvas;
    Image image;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        scroller.viewportBoundsProperty().addListener(new ChangeListener<Bounds>() {
            @Override
            public void changed(ObservableValue<? extends Bounds> observable,
                                Bounds oldValue, Bounds newValue) {
                zoomPane.setMinSize(newValue.getWidth(), newValue.getHeight());
            }
        });
        GraphicsContext gc = canvas.getGraphicsContext2D();
        gc.strokeLine(200, 200, 300, 300);
    }

    public void handlePan(MouseEvent event) {
    }

    public void handleZoom(ScrollEvent event) {
        if (event.getDeltaY() == 0) {
            return;
        }
        double scaleFactor = (event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
        // amount of scrolling in each direction in scrollContent coordinate
        // units
        double oldScale = group.getScaleX();
        double newScale = group.getScaleX() * scaleFactor;
        if (newScale < 1 || newScale > 24) {
            newScale = oldScale;
        }
        Point2D scrollOffset = figureScrollOffset(scrollContent, scroller);
        repositionScroller(scrollContent, scroller, scaleFactor, scrollOffset);
        group.setScaleX(newScale);
        group.setScaleY(newScale);
    }

    public void updateLine(MouseEvent event) {
    }

    public void startDraw(MouseEvent event) {
    }

    public void loadImage(ActionEvent actionEvent) {
        FileChooser fileChooser = new FileChooser();
        File selectedFile = fileChooser.showOpenDialog(Main.stage);

        if (selectedFile == null) {
            JOptionPane.showMessageDialog(null, "No Image selected");
        } else {
            image = new Image("file:" + selectedFile);
            imageView.setImage(image);
        }
    }


    public void getCenterPoint(MouseEvent event) {
        lastMouseCoordinates.set(new Point2D(event.getX(), event.getY()));
    }

    private Point2D figureScrollOffset(Node scrollContent, ScrollPane scroller) {
        double extraWidth = scrollContent.getLayoutBounds().getWidth() - scroller.getViewportBounds().getWidth();
        double hScrollProportion = (scroller.getHvalue() - scroller.getHmin()) / (scroller.getHmax() - scroller.getHmin());
        double scrollXOffset = hScrollProportion * Math.max(0, extraWidth);
        double extraHeight = scrollContent.getLayoutBounds().getHeight() - scroller.getViewportBounds().getHeight();
        double vScrollProportion = (scroller.getVvalue() - scroller.getVmin()) / (scroller.getVmax() - scroller.getVmin());
        double scrollYOffset = vScrollProportion * Math.max(0, extraHeight);
        return new Point2D(scrollXOffset, scrollYOffset);
    }

    private void repositionScroller(Node scrollContent, ScrollPane scroller, double scaleFactor, Point2D scrollOffset) {
        double scrollXOffset = scrollOffset.getX();
        double scrollYOffset = scrollOffset.getY();
        double extraWidth = scrollContent.getLayoutBounds().getWidth() - scroller.getViewportBounds().getWidth();
        if (extraWidth > 0) {
            double halfWidth = scroller.getViewportBounds().getWidth() / 2;
            double newScrollXOffset = (scaleFactor - 1) * halfWidth + scaleFactor * scrollXOffset;
            scroller.setHvalue(scroller.getHmin() + newScrollXOffset * (scroller.getHmax() - scroller.getHmin()) / extraWidth);
        } else {
            scroller.setHvalue(scroller.getHmin());
        }
        double extraHeight = scrollContent.getLayoutBounds().getHeight() - scroller.getViewportBounds().getHeight();
        if (extraHeight > 0) {
            double halfHeight = scroller.getViewportBounds().getHeight() / 2;
            double newScrollYOffset = (scaleFactor - 1) * halfHeight + scaleFactor * scrollYOffset;
            scroller.setVvalue(scroller.getVmin() + newScrollYOffset * (scroller.getVmax() - scroller.getVmin()) / extraHeight);
        } else {
            scroller.setHvalue(scroller.getHmin());
        }
    }
}

FXML文件

public class Main extends Application {
    static Stage stage;
    @Override
    public void start(Stage primaryStage) throws Exception {
        stage = primaryStage;
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
        primaryStage.setScene(new Scene(root, screenBounds.getWidth(), screenBounds.getHeight()));
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

0 个答案:

没有答案