Javafx 2图表和徒手缩放 [英] Javafx 2 chart and freehand zoom
问题描述
此代码绘制XYChart,并使用鼠标右键单击和拖动组合执行自由手绘,而使用鼠标左键单击并拖动执行所选区域的放大.
This code plots an XYChart and using combination of right mouse button click and drag perform free hand draw, while with left mouse button click and drag perform Zoom In on selected area.
我的问题是徒手放大徒手绘制,它总是被翻译.例如,尝试在拐角处的某个地方绘制.
My problem is about zoom on freehand draw it always get translated. For example try to draw somewhere around a corner.
我该如何解决?
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, 1.0, 0, 0);
}
else
{
//Zoom In
double Tgap = 0;
double newLowerBound, newUpperBound, axisShift;
double xScaleFactor, yScaleFactor;
double xaxisShift, yaxisShift;
LineChart<Number, Number> lineChart = (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);
}
}
我认为值得使用这样的东西:
I think it worth using something like this:
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
}
}
推荐答案
与似乎您的坐标基于错误的锚点.您需要找到一个包含图本身的节点,并且仅使用该节点的坐标,而不使用轴或场景.
It seems you coordinates are based on wrong anchors. You need to find a node which contains graph itself and work only with this node's coordinates, not axis or scene.
我甚至建议将所有鼠标事件而不是场景添加到该节点,以避免过多的坐标转换.
I would even advise to add all mouse events to that node instead of scene to avoid excessive coordinates translation.
另一个建议是使用 ScenicView 工具调查您的应用程序,并查看哪些节点具有什么坐标并验证您的数学.
Another advise would be use ScenicView tool to investigate your application and see which nodes has what coordinates and verify your math.
这篇关于Javafx 2图表和徒手缩放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!