3

私は解決できないこの難しい問題にまだ苦しんでいます: 以下のコードは、マウスの左クリックとチャート上でのドラッグ (左上から右下へ) によってズーム (拡大) を実行し、フォームを右下から左上に復元します。

マウスを右クリックしてドラッグすると、フリーハンド描画が実行されます。問題は、描画してからズームすると、描画されたものがずれて、以前に描画した場所にないことです。

これを修正する方法は?

ありがとう

コードは次のとおりです。

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);
    }

}

編集:私はこの提案をしました

Canvas をグラフのオーバーレイとして使用してみてください。その後、キャンバスをスケーリングできます。

しかし、この問題にキャンバスを使用する方法についての手がかりはありません

Edit2:別の提案

座標が間違ったアンカーに基づいているようです。グラフ自体を含むノードを見つけ、軸やシーンではなく、このノードの座標のみを操作する必要があります。過剰な座標変換を避けるために、すべてのマウス イベントをシーンではなくそのノードに追加することをお勧めします。もう 1 つのアドバイスは、ScenicView ツールを使用してアプリケーションを調査し、どのノードがどの座標を持っているかを確認し、計算を検証することです。

編集 3:これらの写真は、私の問題をよりよく説明するのに役立つ場合があります

ここに画像の説明を入力

ここに画像の説明を入力

4

3 に答える 3

0

あなたは、ズームするときに、図面が期待した場所にないという問題について話しているのですよね?

のコードではZoomFreeHand、軸をシフトするコードがコメント化されています。

この問題を解決するには、軸を適切にシフトする必要があると思います。コメントアウトされたコードが機能しない場合でも、描画したものが期待どおりの位置にとどまるように、軸を適切に計算してシフトする必要があります。

于 2012-09-27T18:19:09.947 に答える
0

私は今、問題を少し理解しています。以下は役に立たないかもしれません。しかしとにかく...

正確な要件はわかりませんが、次のようなアイデアが得られるかもしれません。

親の内側にズームする必要があるものすべてを描画します。

Pane root = new Pane();
root.getChildren().add( new Line( 10, 10, 100, 100 ) );

そして、java に内部のすべてのズームを処理させます。次のように、マウス ホイールの内容をズームします。

root.setOnScroll( new ScrollHandler() );

private class ScrollHandler implements EventHandler< ScrollEvent > {
    @Override
    public void handle( ScrollEvent event ) {
        root.setScaleX( root.getScaleX() + event.getDeltaY() * .005 );
        root.setScaleY( root.getScaleY() + event.getDeltaY() * .005 );
    }
}
于 2012-11-08T20:49:33.737 に答える