此代码绘制XYChart并使用鼠标右键单击和拖动的组合执行自由手绘,而用鼠标左键单击并拖动在选定区域执行放大.
我的问题是关于徒手绘制的缩放它总是得到翻译.例如,尝试在拐角处绘制某个地方.
我怎么解决这个问题?
public class Zoom extends Application { Path path;//Add path for freehand BorderPane pane; Rectangle rect; SimpleDoubleProperty rectinitX = new SimpleDoubleProperty(); SimpleDoubleProperty rectinitY = new SimpleDoubleProperty(); SimpleDoubleProperty rectX = new SimpleDoubleProperty(); SimpleDoubleProperty rectY = new SimpleDoubleProperty(); double initXLowerBound = 0,initXUpperBound = 0,initYLowerBound = 0,initYUpperBound = 0; @Override public void start(Stage stage) { stage.setTitle("Lines plot"); final NumberAxis xAxis = new NumberAxis(1,12,1); final NumberAxis yAxis = new NumberAxis(0.53000,0.53910,0.0005); yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) { @Override public String toString(Number object) { return String.format("%7.5f",object); } }); final LineChart<Number,Number> lineChart = new LineChart<Number,Number>(xAxis,yAxis); lineChart.setCreateSymbols(false); lineChart.setAlternativeRowFillVisible(false); lineChart.setAnimated(true); XYChart.Series series1 = new XYChart.Series(); series1.getData().add(new XYChart.Data(1,0.53185)); series1.getData().add(new XYChart.Data(2,0.532235)); series1.getData().add(new XYChart.Data(3,0.53234)); series1.getData().add(new XYChart.Data(4,0.538765)); series1.getData().add(new XYChart.Data(5,0.53442)); series1.getData().add(new XYChart.Data(6,0.534658)); series1.getData().add(new XYChart.Data(7,0.53023)); series1.getData().add(new XYChart.Data(8,0.53001)); series1.getData().add(new XYChart.Data(9,0.53589)); series1.getData().add(new XYChart.Data(10,0.53476)); series1.getData().add(new XYChart.Data(11,0.530123)); series1.getData().add(new XYChart.Data(12,0.53035)); pane = new BorderPane(); pane.setCenter(lineChart); Scene scene = new Scene(pane,800,600); lineChart.getData().addAll(series1); initXLowerBound = ((NumberAxis) lineChart.getXAxis()).getLowerBound(); initXUpperBound = ((NumberAxis) lineChart.getXAxis()).getUpperBound(); initYLowerBound = ((NumberAxis) lineChart.getYAxis()).getLowerBound(); initYUpperBound = ((NumberAxis) lineChart.getYAxis()).getUpperBound(); stage.setScene(scene); path = new Path(); path.setStrokeWidth(1); path.setStroke(Color.BLACK); scene.setOnMouseClicked(mouseHandler); scene.setOnMouseDragged(mouseHandler); scene.setOnMouseEntered(mouseHandler); scene.setOnMouseExited(mouseHandler); scene.setOnMouseMoved(mouseHandler); scene.setOnMousePressed(mouseHandler); scene.setOnMouseReleased(mouseHandler); pane.getChildren().add(path); rect = new Rectangle(); rect.setFill(Color.web("blue",0.1)); rect.setStroke(Color.BLUE); rect.setStrokeDashOffset(50); rect.widthProperty().bind(rectX.subtract(rectinitX)); rect.heightProperty().bind(rectY.subtract(rectinitY)); pane.getChildren().add(rect); stage.show(); } EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent mouseEvent) { if (mouseEvent.getButton() == MouseButton.PRIMARY) { if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) { rect.setX(mouseEvent.getX()); rect.setY(mouseEvent.getY()); rectinitX.set(mouseEvent.getX()); rectinitY.set(mouseEvent.getY()); } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) { rectX.set(mouseEvent.getX()); rectY.set(mouseEvent.getY()); } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_RELEASED) { if ((rectinitX.get() >= rectX.get())&&(rectinitY.get() >= rectY.get())) { LineChart<Number,Number> lineChart = (LineChart<Number,Number>) pane.getCenter(); ((NumberAxis) lineChart.getXAxis()).setLowerBound(initXLowerBound); ((NumberAxis) lineChart.getXAxis()).setUpperBound(initXUpperBound); ((NumberAxis) lineChart.getYAxis()).setLowerBound(initYLowerBound); ((NumberAxis) lineChart.getYAxis()).setUpperBound(initYUpperBound); ZoomFreeHand(path,1.0,0); } else { //Zoom In double Tgap = 0; double newLowerBound,newUpperBound,axisShift; double xScaleFactor,yScaleFactor; double xaxisShift,yaxisShift; LineChart<Number,Number>) pane.getCenter(); // Zoom in Y-axis by changing bound range. NumberAxis yAxis = (NumberAxis) lineChart.getYAxis(); Tgap = yAxis.getHeight()/(yAxis.getUpperBound() - yAxis.getLowerBound()); axisShift = getSceneShiftY(yAxis); yaxisShift = axisShift; newUpperBound = yAxis.getUpperBound() - ((rectinitY.get() - axisShift) / Tgap); newLowerBound = yAxis.getUpperBound() - (( rectY.get() - axisShift) / Tgap); if (newUpperBound > yAxis.getUpperBound()) newUpperBound = yAxis.getUpperBound(); yScaleFactor = (yAxis.getUpperBound() - yAxis.getLowerBound())/(newUpperBound - newLowerBound); yAxis.setLowerBound(newLowerBound); yAxis.setUpperBound(newUpperBound); NumberAxis xAxis = (NumberAxis) lineChart.getXAxis(); Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound()); axisShift = getSceneShiftX(xAxis); xaxisShift = axisShift; newLowerBound = ((rectinitX.get() - axisShift) / Tgap) + xAxis.getLowerBound(); newUpperBound = ((rectX.get() - axisShift) / Tgap) + xAxis.getLowerBound(); if (newUpperBound > xAxis.getUpperBound()) newUpperBound = xAxis.getUpperBound(); xScaleFactor = (xAxis.getUpperBound() - xAxis.getLowerBound())/(newUpperBound - newLowerBound); xAxis.setLowerBound( newLowerBound ); xAxis.setUpperBound( newUpperBound ); ZoomFreeHand(path,xScaleFactor,yScaleFactor,xaxisShift,yaxisShift); } // Hide the rectangle rectX.set(0); rectY.set(0); } } else if (mouseEvent.getButton() == MouseButton.SECONDARY) //free hand graphics { if(mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED){ path.getElements().clear(); path.getElements().add(new MoveTo(mouseEvent.getX(),mouseEvent.getY())); } else if(mouseEvent.getEventType()==MouseEvent.MOUSE_DRAGGED){ path.getElements().add(new LineTo(mouseEvent.getX(),mouseEvent.getY())); } } } }; private static double getSceneShiftX(Node node) { double shift = 0; do { shift += node.getLayoutX(); node = node.getParent(); } while (node != null); return shift; } private static double getSceneShiftY(Node node) { double shift = 0; do { shift += node.getLayoutY(); node = node.getParent(); } while (node != null); return shift; } private static void ZoomFreeHand(Path path,double xScaleFactor,double yScaleFactor,double xaxisShift,double yaxisShift) { double layX,layY; layX = path.getLayoutX(); layY = path.getLayoutY(); path.setScaleX(xScaleFactor); path.setScaleY(yScaleFactor); path.setTranslateX(xaxisShift); path.setTranslateY(yaxisShift); } public static void main(String[] args) { launch(args); } }
我认为值得使用这样的东西:
ObservableList<PathElement> mypathElements = path.getElements(); for (int i = 0; i < mypathElements.size(); i++) { final PathElement element = mypathElements.get(i); if (element instanceof MoveTo) { final MoveTo move = (MoveTo)element; //change move coordinates } else if (element instanceof LineTo) { final LineTo line = (LineTo)element; //change line coordinates } }
解决方法
与
Javafx 2 chart resize with freehand draw相同的问题和相同的答案:
看来你的坐标是基于错误的锚点.您需要找到一个包含图形本身的节点,并且只能使用此节点的坐标,而不是轴或场景.
我甚至建议将所有鼠标事件添加到该节点而不是场景,以避免过多的坐标转换.
另一个建议是使用ScenicView工具调查您的应用程序,看看哪些节点有什么坐标并验证您的数学.