2012-05-04 3 views
7

Ce code trace un XYChart et en utilisant la combinaison du bouton droit de la souris, cliquez et glissez pour dessiner à main levée, tandis qu'avec le bouton gauche de la souris cliquez et faites glisser Zoomer sur la zone sélectionnée.Javafx 2 graphique et zoom à main levée

Mon problème est de zoomer à main levée, il est toujours traduit. Par exemple, essayez de dessiner quelque part dans un coin.

Comment puis-je résoudre ce problème?

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

Je pense qu'il vaut la peine d'utiliser quelque chose comme ceci:

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

J'ai fait quelques tests mais je n'ai pas eu de succès, je pense que le problème est dû à la "correspondance de traduction" incorrecte – famedoro

Répondre

3

Même problème que dans Javafx 2 chart resize with freehand draw et même réponse:

Il semble que les coordonnées sont basées sur les points d'ancrage mal. Vous devez trouver un nœud qui contient le graphique lui-même et travailler uniquement avec les coordonnées de ce nœud, pas d'axe ou de scène.

Je conseillerais même d'ajouter tous les événements de souris à ce noeud au lieu de la scène pour éviter la traduction excessive de coordonnées.

Un autre conseil serait d'utiliser l'outil ScenicView pour étudier votre application et voir quels nœuds ont quelles coordonnées et vérifier vos calculs.

+1

J'ai mis à jour le lien vers ScenicView, comme celui là juste rappelé à cette question. Je suppose que je l'ai indiqué au bon endroit, vous voudrez peut-être vérifier. –

+0

droite, merci !! –

1

Je vous recommande de remplacer ceux-ci:

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

avec Node.localToScene, Node.sceneToLocal méthodes de conversion qui ont des points ou Bounds comme arguments.

+0

Pourriez-vous poster un exemple? – famedoro

+0

'node.localToScene (0, 0) .getX(); // au lieu de getSceneShiftX() ' ' node.localToScene (0, 0) .getY(); // à la place de getSceneShiftY() ' La seule différence est que ces méthodes utiliseront également d'autres transformations de coordonnées en plus de layoutX et de layoutY (telles que rotate, translate, etc.) –

Questions connexes