JavaFX 2.x;仍然有绘制图表+缩放的问题 [英] JavaFX 2.x; Still problems with draw on chart + zoom

查看:1383
本文介绍了JavaFX 2.x;仍然有绘制图表+缩放的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我仍然在努力解决这个难题,我不能解决:下面的代码执行缩放(放大)通过鼠标左键单击&



鼠标右键单击并拖动可执行一次免费手绘:问题(从左到右)



如何解决这个问题?



感谢



以下是代码:

  public class Zoom extends应用程序{

路径路径; //添加自由路径
BorderPane窗格;
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 CategoryAxis xAxis = new CategoryAxis();
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 = new Scene(lineChart,800,600);
场景scene =新场景(窗格,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);

//root.getChildren().add(lineChart);
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())){
// Condizioni Iniziali
LineChart< Number,Number> lineChart =(LineChart< Number,Number>)pane.getCenter();

((NumberAxis)lineChart.getXAxis())。setLowerBound(ini​​tXLowerBound);
((NumberAxis)lineChart.getXAxis())。setUpperBound(ini​​tXUpperBound);

((NumberAxis)lineChart.getYAxis())。setLowerBound(ini​​tYLowerBound);
((NumberAxis)lineChart.getYAxis())。setUpperBound(ini​​tYUpperBound);

ZoomFreeHand(path,1.0,1.0,0,0);

} else {
//放大

double Tgap = 0;
double newLowerBound,newUpperBound,axisShift;
double xScaleFactor,yScaleFactor;
double xaxisShift,yaxisShift;
// System.out.println(Zoom bounds:[+ rectinitX.get()+,+ rectinitY.get()
// +] [+ rectX.get )+,+ rectY.get()+]);
// System.out.println(TODO:根据这些缩放坐标确定绑定范围。

// TODO:根据此缩放坐标确定绑定范围。
// LineChart< String,Number> lineChart =(LineChart< String,Number>)pane.getCenter();
LineChart< Number,Number> lineChart =(LineChart< Number,Number>)pane.getCenter();

//通过改变绑定范围来放大Y轴。
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);


// System.out.println((a)rectinitY.get()+ rectinitY.get()+rectY.get()+ rectY.get );
// System.out.println((a)Tgap+ Tgap +axisShift+ axisShift +yAxis.getLowerBound()
// + yAxis.getLowerBound()++ yAxis。 getUpperBound());

if(newUpperBound> yAxis.getUpperBound())
newUpperBound = yAxis.getUpperBound();

yScaleFactor =(yAxis.getUpperBound() - yAxis.getLowerBound())/(newUpperBound - newLowerBound);
yAxis.setLowerBound(newLowerBound);
yAxis.setUpperBound(newUpperBound);

// System.out.println((b)yAxis.getLowerBound()+ yAxis.getLowerBound()+
// + yAxis.getUpperBound());

//通过删除第一个和最后一个数据值来放大X轴。
//注意:也许更好如果categoryaxis被numberaxis替换,那么设置
// LowerBound和UpperBound将是可用的。
/ *
XYChart.Series series1 = lineChart.getData()。get(0);
if(!series1.getData()。isEmpty()){
series1.getData()。remove(0);
series1.getData()。remove(series1.getData()。size() - 1);
}
* /

NumberAxis xAxis =(NumberAxis)lineChart.getXAxis();

// System.out.println((a)xAxis.getLowerBound()+ xAxis.getLowerBound()+
// + xAxis.getUpperBound());

Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());
// newXlower =(rectinitX.get()/ Tgap)+ xAxis.getLowerBound();
// newXupper =(rectX.get()/ Tgap)+ 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);



// System.out.println((b)xAxis.getLowerBound()+ xAxis.getLowerBound()++ xAxis.getUpperBound ;

ZoomFreeHand(path,xScaleFactor,yScaleFactor,xaxisShift,yaxisShift);
}
//隐藏矩形
rectX.set(0);
rectY.set(0);
}
} // end if(mouseEvent.getButton()== MouseButton.PRIMARY)
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()));
}
} // end if(mouseEvent.getButton()== MouseButton.SECONDARY)
}
};

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){
/ *
ObservableList< PathElement> ListPath = path.getElements();

if(ListPath.size()!= 0){
MoveTo moveto;
((MoveTo)(ListPath.get(0)))。setX(0-axisShiftX);
((MoveTo)(ListPath.get(0)))。setY(0-axisShiftY);
}
* /

path.setScaleX(xScaleFactor);
path.setScaleY(yScaleFactor);
path.setTranslateX(xaxisShift);
path.setTranslateY(yaxisShift);
}

public static void main(String [] args){
launch(args);
}

}

strong>我有这个建议



尝试使用Canvas作为图表顶部的叠加层。



,但没有关于如何使用canvas来处理这个问题的线索



Edit2:另一个建议



您似乎坐标是基于错误的锚点。您需要找到一个包含图形本身的节点,并且只使用该节点的坐标,而不是轴或场景。
我甚至建议将所有鼠标事件添加到该节点,而不是场景,以避免过多的坐标转换。
另一个建议是使用ScenicView工具调查您的应用程序,并查看哪些节点有什么坐标和验证您的数学。



3:这些照片可能有助于更好地解释我的问题





解决方案

pre> yAxis.setLowerBound(10);
yAxis.setUpperBound(100);
yAxis.setTickUnit(5);


I am still struggling with this hard problem I can't solve: the code below performs a zoom (magnify) by left mouse click & drag on the chart (from up left to down right) and restore back form down right to up left.

Right mouse click and drag performs a free hand draw: the problem is that if I draw then zoom, what drawn is displaced and it is not where I previously drawn.

How to fix this?

Thanks

Here's the code:

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 CategoryAxis xAxis = new CategoryAxis();
        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(lineChart, 800, 600);
        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);

        //root.getChildren().add(lineChart);
        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();
    }
    // sum layout shift against parent until we ascend to scene


    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())) {
                    //Condizioni Iniziali
                    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;
//                  System.out.println("Zoom bounds : [" + rectinitX.get() + ", " +rectinitY.get()
//                                     + "] ["+ rectX.get()+", "+rectY.get()+"]");
//                  System.out.println("TODO: Determine bound ranges according these zoom coordinates.\n");

                    // TODO: Determine bound ranges according this zoom coordinates.
                    //LineChart<String, Number> lineChart = (LineChart<String, Number>) pane.getCenter();
                    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);


//                  System.out.println("(a) rectinitY.get() "+rectinitY.get()+" rectY.get() "+rectY.get());
//                  System.out.println("(a) Tgap "+Tgap+" axisShift "+axisShift+" yAxis.getLowerBound() "
//                                     + yAxis.getLowerBound()+ " " + yAxis.getUpperBound());

                    if (newUpperBound > yAxis.getUpperBound())
                        newUpperBound = yAxis.getUpperBound();

                    yScaleFactor = (yAxis.getUpperBound() - yAxis.getLowerBound())/(newUpperBound - newLowerBound);
                    yAxis.setLowerBound(newLowerBound);
                    yAxis.setUpperBound(newUpperBound);

//                  System.out.println("(b) yAxis.getLowerBound() " + yAxis.getLowerBound()+ " "
//                                     + yAxis.getUpperBound());

                    // Zoom in X-axis by removing first and last data values.
                    // Note: Maybe better if categoryaxis is replaced by numberaxis then setting the
                    // LowerBound and UpperBound will be avaliable.
/*
                    XYChart.Series series1 = lineChart.getData().get(0);
                    if (!series1.getData().isEmpty()) {
                        series1.getData().remove(0);
                        series1.getData().remove(series1.getData().size() - 1);
                    }
 */

                    NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();

//                  System.out.println("(a) xAxis.getLowerBound() " + xAxis.getLowerBound()+ " "
//                                     + xAxis.getUpperBound());            

                    Tgap = xAxis.getWidth()/(xAxis.getUpperBound() - xAxis.getLowerBound());            
//                  newXlower = (rectinitX.get()/Tgap) + xAxis.getLowerBound();
//                  newXupper = (rectX.get()/Tgap)+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 );



//                  System.out.println("(b) xAxis.getLowerBound() "+xAxis.getLowerBound()+" "+xAxis.getUpperBound());

                    ZoomFreeHand(path, xScaleFactor, yScaleFactor, xaxisShift, yaxisShift);
                }
                // Hide the rectangle
                rectX.set(0);
                rectY.set(0);
            }
        }// end if (mouseEvent.getButton() == MouseButton.PRIMARY)
        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()));
            }
        } //end if (mouseEvent.getButton() == MouseButton.SECONDARY)
    }
};

    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) {
/*
        ObservableList<PathElement> ListPath = path.getElements();

        if (ListPath.size() != 0) {
            MoveTo moveto;
            ((MoveTo)(ListPath.get(0))).setX(0-axisShiftX);    
            ((MoveTo)(ListPath.get(0))).setY(0-axisShiftY);
        }
*/

        path.setScaleX(xScaleFactor);
        path.setScaleY(yScaleFactor);
        path.setTranslateX(xaxisShift);
        path.setTranslateY(yaxisShift);
    }

    public static void main(String[] args) {
        launch(args);
    }

}

Edit: I have had this suggestion

Try using Canvas as an overlay on top of the chart. You can then just scale the Canvas.

but have no clue about how to use canvas for this issue

Edit2: Another suggestion

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. Another advise would be use ScenicView tool to investigate your application and see which nodes has what coordinates and verify your math.

Edit 3: These pictures may help in better explaining my issue

解决方案

I solve this problem by using,

   yAxis.setLowerBound(10);
    yAxis.setUpperBound(100);
    yAxis.setTickUnit(5);

这篇关于JavaFX 2.x;仍然有绘制图表+缩放的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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