问题描述
干杯!
我必须在JavaFX画布上绘制和编辑SVGLines。我已经设法设法将自画线转换为SVG路径,并将其附加在Canvas GraphicalContext上。现在,我想放大画布,但是如果我放大,则线条会变得模糊。不能在STackPane而不是Canvas上进行缩放,因为我需要绘制线条。 SVG线应为锐利n以便对其进行编辑。谢谢您的帮助!
公共类控制器{
public StackPane pane;
public Canvas canvas;
public ToggleButton lineButton;
private Stage stage;
private ObservableList<SVGPath> paths;
private GraphicsContext gc;
public void run() {
gc = canvas.getGraphicsContext2D();
paths = FXCollections.observableArrayList();
gc.setstroke(Color.BLACK);
gc.setlinewidth(1.0);
Line line = new Line();
canvas.setonmousepressed(e->{
if(lineButton.isSelected()){
line.setStartX(e.getX());
line.setStartY(e.getY());
}
});
canvas.setonMouseReleased(e->{
if(lineButton.isSelected()){
line.setEndX(e.getX());
line.setEndY(e.getY());
//gc.strokeLine(line.getStartX(),line.getStartY(),line.getEndX(),line.getEndY());
SVGPath svgline = linetosvg(line);
draw(svgline);
paths.add(svgline);
}
});
canvas.setonScroll(e->{
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor =
(e.getDeltaY() > 0)
? 1.1
: 1/1.1;
canvas.setScaleX(canvas.getScaleX() >= 0.5?canvas.getScaleX() * scaleFactor:0.5);
canvas.setScaleY(canvas.getScaleY() >= 0.5? canvas.getScaleY() * scaleFactor:0.5);
});
}
public SVGPath linetosvg(Line line){
SVGPath p = new SVGPath();
final StringBuilder fxPath = new StringBuilder();
fxPath.append("M ").append(line.getStartX()).append(" ").append(line.getStartY()).append(" ")
.append("L ").append(line.getEndX()).append(" ").append(line.getEndY());
p.setContent(fxPath.toString());
return p;
}
public void draw (SVGPath path){
gc.beginPath();
gc.setFill(path.getFill());
gc.setstroke(path.getstroke());
gc.setlinewidth(path.getstrokeWidth());
gc.appendSVGPath(path.getContent());
gc.stroke();
gc.fill();
}
public Stage getStage() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
public ObservableList<SVGPath> getPaths() {
return paths;
}
public void setPaths(ObservableList<SVGPath> paths) {
this.paths = paths;
}
}
公共类Main扩展Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
Controller controller = loader.getController();
controller.run();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
解决方法
我解决了问题! 对于任何有兴趣的人,我将在下面发布我的消息!诀窍是缩放GraphicalContext,计算totalScale缩放并重画Lines;)。现在,如果您还没有选择行按钮,也可以重新定位画布。如果要在缩放后绘制直线,则需要使用在画布上完成的totalScaling来定义X-Y坐标。
public class Controller {
public StackPane pane;
public Canvas canvas;
public ToggleButton lineButton;
private Stage stage;
private ObservableList<SVGPath> paths;
private GraphicsContext gc;
//because we dont have any getScale Methods for GrapficsContext we neet to calculate by ourselves
private double scale = 1.0;
private double totalScale = 1.0;
public void run() {
//pane same size as the start-canvas in order to calculate the scale
pane.setMinSize(canvas.getWidth(),canvas.getHeight());
gc = canvas.getGraphicsContext2D();
paths = FXCollections.observableArrayList();
gc.setStroke(Color.BLACK);
gc.setLineWidth(1.0);
Line line = new Line();
Line drag = new Line();
canvas.setOnMousePressed(e->{
if(lineButton.isSelected()){
//set the X-Y Positions in relation to our scaling we may have done
line.setStartX(e.getX() / totalScale);
line.setStartY(e.getY() / totalScale);
}
else{
//calculate an drag Action in order to reposition the canvas
drag.setStartX(e.getX() / totalScale);
drag.setStartY(e.getY() / totalScale);
}
});
canvas.setOnMouseReleased(e->{
if(lineButton.isSelected()){
line.setEndX(e.getX() / totalScale);
line.setEndY(e.getY() / totalScale);
//gc.strokeLine(line.getStartX(),line.getStartY(),line.getEndX(),line.getEndY());
SVGPath svgline = linetosvg(line);
draw(svgline);
paths.add(svgline);
}
else{
drag.setEndX(e.getX() / totalScale);
drag.setEndY(e.getY() / totalScale);
//calculate the Delta in Movement we did,slower Movement f we are very close or far from the object on tha Canvas
double deltaX = totalScale>=1?Math.abs(drag.getEndX() - drag.getStartX()) / totalScale:Math.abs(drag.getEndX() - drag.getStartX()) * totalScale;
double deltaY = totalScale>=1?Math.abs(drag.getEndY() - drag.getStartY()) / totalScale:Math.abs(drag.getEndY() - drag.getStartY()) * totalScale;
canvas.setTranslateX(drag.getStartX() < drag.getEndX() ? canvas.getTranslateX() + deltaX : canvas.getTranslateX() - deltaX);
canvas.setTranslateY(drag.getStartY() < drag.getEndY() ? canvas.getTranslateY() + deltaY : canvas.getTranslateY() - deltaY);
}
});
canvas.setOnScroll(e->{
if (e.getDeltaY() == 0) {
return;
}
double scaleFactor =
(e.getDeltaY() > 0)
? 1.1
: 1/1.1;
//delete everything,because we need to redraw
gc.clearRect(0,canvas.getWidth(),canvas.getHeight());
//In order to make the zooming fluenter...
scale = scale==1?scale * scaleFactor:1.0;
//scale the GraphicalContext and rezize the Canvas in order to display everything
gc.scale(scale,scale);
canvas.setWidth(canvas.getWidth()*scale);
canvas.setHeight(canvas.getHeight()*scale);
//count every scale in order to calc the totalScaling done
totalScale = totalScale * scale;
for (int i = 0; i < paths.size(); i++) {
draw(paths.get(i));
}
});
}
public SVGPath linetosvg(Line line){
SVGPath p = new SVGPath();
final StringBuilder fxPath = new StringBuilder();
fxPath.append("M ").append(line.getStartX()).append(" ").append(line.getStartY()).append(" ")
.append("L ").append(line.getEndX()).append(" ").append(line.getEndY());
p.setContent(fxPath.toString());
return p;
}
public void draw (SVGPath path){
gc.beginPath();
gc.setFill(path.getFill());
gc.setStroke(path.getStroke());
gc.setLineWidth(path.getStrokeWidth());
gc.appendSVGPath(path.getContent());
gc.stroke();
gc.fill();
}
public Stage getStage() {
return stage;
}
public void setStage(Stage stage) {
this.stage = stage;
}
public ObservableList<SVGPath> getPaths() {
return paths;
}
public void setPaths(ObservableList<SVGPath> paths) {
this.paths = paths;
}
}
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root));
Controller controller = loader.getController();
controller.run();
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
输出