2012-05-04 36 views
7

Mã này vẽ sơ đồ XYChart và sử dụng kết hợp chuột phải và kéo để thực hiện thao tác vẽ tay miễn phí, trong khi nhấn và giữ chuột trái để thực hiện Phóng to trên vùng đã chọn.Biểu đồ Javafx 2 và tự do phóng to

Vấn đề của tôi là phóng to thu nhỏ tự do vẽ nó luôn được dịch. Ví dụ cố gắng vẽ một nơi nào đó xung quanh một góc.

Tôi làm cách nào để giải quyết vấn đề này?

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

Tôi nghĩ rằng nó có giá trị sử dụng một cái gì đó như thế này:

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

Tôi đã thực hiện một số thử nghiệm nhưng tôi không thành công, tôi nghĩ vấn đề là do "khớp dịch" không chính xác – famedoro

Trả lời

3

Cùng một vấn đề như trong Javafx 2 chart resize with freehand draw và cùng câu trả lời:

Có vẻ như bạn tọa độ được dựa trên neo sai. Bạn cần phải tìm một nút có chứa đồ thị và chỉ làm việc với các tọa độ của nút này, chứ không phải trục hoặc cảnh.

Tôi thậm chí khuyên bạn nên thêm tất cả sự kiện chuột vào nút đó thay vì cảnh để tránh dịch tọa độ quá mức.

Một tư vấn khác sẽ sử dụng công cụ ScenicView để điều tra ứng dụng của bạn và xem các nút nào có tọa độ và xác minh toán học của bạn.

+1

Tôi đã cập nhật liên kết đến ScenicView, như một câu trả lời cho câu hỏi này. Tôi cho rằng tôi đã chỉ đúng nơi, bạn có thể muốn kiểm tra lại nó. –

+0

đúng, cảm ơn !! –

1

tôi khuyên bạn nên thay thế những:

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

với Node.localToScene, Node.sceneToLocal phương pháp chuyển đổi mà mất điểm hoặc Bounds như các đối số.

+0

Bạn có thể đăng một ví dụ không? – famedoro

+0

'node.localToScene (0, 0) .getX(); // thay vì getSceneShiftX() ' ' node.localToScene (0, 0) .getY(); // thay vì getSceneShiftY() ' Sự khác biệt duy nhất là các phương thức này cũng sẽ sử dụng các phép biến đổi tọa độ khác ngoài layoutX và layoutY (như xoay, dịch, v.v.) –

Các vấn đề liên quan