2014-09-23 2 views
2

У меня проблема с масштабирующей способностью для моих фигур. Я хочу использовать систему координат, которую нарисовал бы мой собственный, который имеет некоторые формы. Этим формам нужна функция масштабирования. После масштабирования фигур они перемещаются, потому что масштабирование происходит в центре каждой фигуры. Чтобы реагировать на это движение, я пересчитываю происхождение. Но если я масштабируюся много раз, форма все равно удаляется от источника. Я не знаю почему. Может ли кто-нибудь объяснить это поведение? Далее я попытаюсь пересчитать ширину хода до 1px.JavaFX Scaling Shape без перемещения источника

Спасибо!

Мой код:

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.geometry.Bounds; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Line; 
import javafx.scene.shape.Polyline; 
import javafx.stage.Stage; 

public class ScaleTest extends Application { 

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

    @Override 
    public void start(Stage stage) throws Exception { 
     Pane root = new Pane(); 
     Scene scene = new Scene(root, 800, 600, Color.WHITE); 
     stage.setScene(scene); 

     Polyline line1 = new Polyline(new double[] { 50, 50, 50, 150, 150, 150, 
       150, 50, 50, 50 }); 
     line1.setStrokeWidth(1); 

     Group polylines = new Group(); 
     polylines.getChildren().add(line1); 

     Line xAxis = new Line(0, 50, 800, 50); 
     Line yAxis = new Line(50, 0, 50, 800); 

     root.setScaleY(-1); 
     root.getChildren().addAll(xAxis, yAxis); 
     root.getChildren().add(polylines); 

     scene.setOnScroll(new EventHandler<ScrollEvent>() { 

      @Override 
      public void handle(ScrollEvent event) { 
       double scale = 0; 
       if (event.getDeltaY() < 0) { 
        scale = -0.1; 
       } else { 
        scale = 0.1; 
       } 

       Bounds beforeScaling = polylines.getBoundsInParent(); 
       polylines.setScaleX(polylines.getScaleX() + scale); 
       polylines.setScaleY(polylines.getScaleY() + scale); 
       Bounds afterScaling = polylines.getBoundsInParent(); 
       polylines.setTranslateX(polylines.getTranslateX() 
         + beforeScaling.getMinX() - afterScaling.getMinX()); 
       polylines.setTranslateY(polylines.getTranslateY() 
         + beforeScaling.getMinY() - afterScaling.getMinY()); 

       //optional 
       line1.setStrokeWidth(1/polylines.getScaleX()); 
      } 

     }); 

     stage.show(); 
    } 
} 

ответ

3

Я не знаю, почему он «дрейфует» - возможно, это просто накопление ошибок округления. Более простой подход - использовать трансформацию Scale. При этом вы можете указать точку «поворота», по которой происходит масштабирование.

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.input.ScrollEvent; 
import javafx.scene.layout.Pane; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Line; 
import javafx.scene.shape.Polyline; 
import javafx.scene.transform.Scale; 
import javafx.stage.Stage; 

public class ScaleTest extends Application { 

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

    @Override 
    public void start(Stage stage) throws Exception { 
     Pane root = new Pane(); 
     Scene scene = new Scene(root, 800, 600, Color.WHITE); 
     stage.setScene(scene); 

     Polyline line1 = new Polyline(new double[] { 50, 50, 50, 150, 150, 150, 
       150, 50, 50, 50 }); 
     line1.setStrokeWidth(1); 

     Group polylines = new Group(); 
     polylines.getChildren().add(line1); 

     Line xAxis = new Line(0, 50, 800, 50); 
     Line yAxis = new Line(50, 0, 50, 800); 

     root.setScaleY(-1); 
     root.getChildren().addAll(xAxis, yAxis); 
     root.getChildren().add(polylines); 

     Scale scale = new Scale(); 
     scale.setPivotX(50); 
     scale.setPivotY(50); 
     polylines.getTransforms().add(scale); 

     scene.setOnScroll(new EventHandler<ScrollEvent>() { 

      @Override 
      public void handle(ScrollEvent event) { 
       double scaleDelta = 0; 
       if (event.getDeltaY() < 0) { 
        scaleDelta = -0.1; 
       } else { 
        scaleDelta = 0.1; 
       } 
       scale.setX(scale.getX() + scaleDelta); 
       scale.setY(scale.getY() + scaleDelta); 
       //optional 
       line1.setStrokeWidth(1/scale.getX()); 
      } 

     }); 

     stage.show(); 
    } 
} 
+0

Oh man many many thanks. Мне потребовались дни, чтобы избавиться от этого! Он отлично работает! – user2246718

+0

FWIW, I ** think ** «дрейфующий» возникает, потому что линейный ход (который отличен от нуля) сосредоточен на границах формы. Так что, если у вас есть линия шириной 1px, ваши вычисления границ будут уменьшены на 0,5 пикселя. По мере увеличения масштаба это расхождение также увеличивается. Но это довольно академично, просто используйте метод преобразования. –