这是另一个缩放问题,请先花点时间阅读。
我正在创建一个简单的绘画应用程序,需要在图像上绘制。当我放大/缩小绘图时,请留在其绘制的图像上。我正在使用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);
}
}