2012-05-04 21 views
7

このコードはXYマウスをプロットし、右マウスボタンクリックとドラッグの組み合わせを使用してフリーハンドドローを行い、左マウスボタンをクリックしてドラッグすると、選択領域を拡大します。Javafx 2のチャートとフリーハンドzoom

私の問題は、フリーハンドドローをズームすると常に翻訳されてしまうことです。たとえば、コーナーの周りのどこかに描画しようとします。

どうすればこの問題を解決できますか?

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

私は価値がある。このような何か使用したと思う:

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 
    } 
} 
+0

私はいくつかのテストをしましたが、私は成功しませんでした。私はこの問題が誤った "翻訳一致"のためだと思っています。 – famedoro

答えて

3

Javafx 2 chart resize with freehand drawのように同じ問題と同じ答え:

をそれはあなた座標が間違ったアンカーに基づいているようです。グラフ自体を含むノードを見つける必要があり、軸やシーンではなく、このノードの座標でのみ動作します。

座標の過度の変換を避けるために、シーンの代わりにそのノードにすべてのマウスイベントを追加することをお勧めします。

ScenicViewツールを使用してアプリケーションを調査し、どのノードにどの座標があるかを確認し、数学を検証することをお勧めします。

+1

この質問に戻ると、ScenicViewへのリンクが更新されました。私はそれが正しい場所を指摘したと仮定します、あなたはそれを再度チェックしたいかもしれません。 –

+0

右、ありがとう! –

1

私はそれらを交換するお勧めします:

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

Node.localToSceneと、引数としてのポイントや境界を取っNode.sceneToLocal変換方法。

+0

例を投稿できますか? – famedoro

+0

'node.localToScene(0、0).getX(); //代わりにgetSceneShiftX() ' ' node.localToScene(0、0).getY(); //代わりにgetSceneShiftY() ' 唯一の違いは、これらのメソッドはlayoutXとlayoutY以外の他の座標変換も使用することです(rotate、translateなど) –