Javafx 2图表和徒手缩放 [英] Javafx 2 chart and freehand zoom

查看:134
本文介绍了Javafx 2图表和徒手缩放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码绘制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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆