JavaFx - 调整矩形大小



我尝试允许用户在javafx中拖动/调整矩形的大小。javafx 中的矩形使用 TopLeft-X、Y、高度和宽度进行绘制。

我试图做的是在矩形的每个角有 4 个手柄,以允许用户拖动手柄。这将导致调整矩形的大小。

我的应用程序抛出一个堆栈溢出异常,我知道这是由侦听器的递归调用引起的。

我忘了什么吗?还是有一些不必要的听众?

public class Handler extends Circle
{
    private double deltaX;
    private double deltaY;
    private static final double DEFAULT_RADIUS = 10;
    private static final Color DEFAULT_COLOR = Color.GOLD;
    private DoubleProperty xProperty;
    private DoubleProperty yProperty;
    public Handler(DoubleProperty xProperty, DoubleProperty yProperty)
    {
        super(DEFAULT_RADIUS, DEFAULT_COLOR);
        this.xProperty = xProperty;
        this.yProperty = yProperty;
        init();
    }   
    private void init()
    {
        setFill(DEFAULT_COLOR.deriveColor(1, 1, 1, 0.5));
        setStroke(DEFAULT_COLOR);
        setStrokeWidth(2);
        setStrokeType(StrokeType.OUTSIDE);
        centerXProperty().bind(xProperty);
        centerYProperty().bind(yProperty);
        setOnMousePressed(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent mouseEvent)
            {
                mouseEvent.consume();
                deltaX = getCenterX() - mouseEvent.getX();
                deltaY = getCenterY() - mouseEvent.getY();
                getScene().setCursor(javafx.scene.Cursor.MOVE);
            }
        });
        setOnMouseReleased(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent mouseEvent)
            {
                getScene().setCursor(javafx.scene.Cursor.HAND);
            }
        });
        setOnMouseEntered(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent mouseEvent)
            {
                if (!mouseEvent.isPrimaryButtonDown())
                {
                    getScene().setCursor(javafx.scene.Cursor.HAND);
                }
            }
        });
        setOnMouseExited(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent mouseEvent)
            {
                if (!mouseEvent.isPrimaryButtonDown())
                {
                    getScene().setCursor(javafx.scene.Cursor.DEFAULT);
                }
            }
        });
        setOnMouseDragged(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent mouseEvent)
            {
                double newX = mouseEvent.getX() + deltaX;
                double newY = mouseEvent.getY() + deltaY;
                if (newX > 0 && newX < getScene().getWidth())
                {                   
                    xProperty.set(newX);
                }
                if (newY > 0 && newY < getScene().getHeight())
                {                   
                    yProperty.set(newY);
                }
            }
        });
    }
    //JavaFx Accessor and mutator
}

public class CustomRectangle extends Rectangle
{   
    private DoubleProperty topRightX;
    private DoubleProperty topRightY;
    private DoubleProperty btmLeftX;
    private DoubleProperty btmLeftY;
    private DoubleProperty btmRightX;
    private DoubleProperty btmRightY;
    private DoubleProperty customeWidth;
    private DoubleProperty customHeight;
    public CustomRectangle()
    {
        super();
        init();
    }
    public CustomRectangle(double x, double y, double width, double height)
    {
        super(x, y, width, height);
        init();
    }
    public CustomRectangle(double width, double height, Paint fill)
    {
        super(width, height, fill);
        init();
    }
    public CustomRectangle(double width, double height)
    {
        super(width, height);
        init();
    }
    private void init()
    {       
        topRightX = new SimpleDoubleProperty();
        topRightY = new SimpleDoubleProperty();
        btmLeftX = new SimpleDoubleProperty();
        btmLeftY = new SimpleDoubleProperty();
        btmRightX = new SimpleDoubleProperty();
        btmRightY = new SimpleDoubleProperty();
        topRightX.addListener((observable, oldValue, newValue) ->
        {
            this.setWidth(this.getWidth() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
        topRightY.addListener((observable, oldValue, newValue) ->
        {
            this.setY(newValue.doubleValue());
            this.setHeight(this.getHeight() - (newValue.doubleValue() - oldValue.doubleValue()));
        });
        btmLeftX.addListener((observable, oldValue, newValue) ->
        {
            this.setX(newValue.doubleValue());
            this.setWidth(this.getWidth() - (newValue.doubleValue() - oldValue.doubleValue()));
        });
        btmLeftY.addListener((observable, oldValue, newValue) ->
        {
            this.setY(newValue.doubleValue());
            this.setHeight(this.getHeight() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
        btmRightX.addListener((observable, oldValue, newValue) ->
        {
            this.setWidth(this.getWidth() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
        btmRightY.addListener((observable, oldValue, newValue) ->
        {
            this.setHeight(this.getHeight() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
        this.xProperty().addListener((observable, oldValue, newValue) ->
        {           
            btmLeftX.set(newValue.doubleValue());
            topRightX.set(newValue.doubleValue() + this.getWidth());
            btmRightX.set(newValue.doubleValue() + this.getWidth());
        });
        this.yProperty().addListener((observable, oldValue, newValue) ->
        {           
            btmLeftY.set(newValue.doubleValue() + this.getHeight());
            topRightY.set(newValue.doubleValue());
            btmRightY.set(newValue.doubleValue() + this.getHeight());
        });
        this.widthProperty().addListener((observable, oldValue, newValue) ->
        {
            topRightX.set(this.getX() + (newValue.doubleValue() - oldValue.doubleValue()));
            btmRightX.set(this.getX() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
        this.heightProperty().addListener((observable, oldValue, newValue) ->
        {
            btmLeftY.set(this.getY() + (newValue.doubleValue() - oldValue.doubleValue()));
            btmRightY.set(this.getY() + (newValue.doubleValue() - oldValue.doubleValue()));
        });
    } 
    //JavaFx Accessor and Mutator
}
public class FeatureHelper
{   
    private static double orgSceneX;    
    private static double orgSceneY;
    private static double orgTranslateX;
    private static double orgTranslateY;
    public static CustomRectangle createDraggableRectangle(double x, double y, double width, double height,
            boolean resizeImage)
    {
        CustomRectangle rect = new CustomRectangle(x, y, width, height);
        // top left resize handle:
        Handler topLeftHandle = new Handler(rect.topLeftXProperty(), rect.topLeftYProperty());
        // top right resize handle:
        Handler topRightHandle = new Handler(rect.topRightXProperty(), rect.topRightYProperty());
        // bottom left resize handle:
        Handler btmLeftHandle = new Handler(rect.btmLeftXProperty(), rect.btmLeftYProperty());
        // bottom right resize handle:
        Handler btmRightHandle = new Handler(rect.btmRightXProperty(), rect.btmRightYProperty());
        // force circles to live in same parent as rectangle:
        rect.parentProperty().addListener((obs, oldParent, newParent) ->
        {
            for (Circle c : Arrays.asList(topLeftHandle, topRightHandle, btmLeftHandle, btmRightHandle))
            {
                if (newParent != null)
                {
                    ((Pane) newParent).getChildren().add(c);
                }
            }
        });
        rect.setOnMousePressed(event -> 
        {
            event.consume();
            orgSceneX = event.getSceneX();
            orgSceneY = event.getSceneY();
            Node p = ((Node) (event.getSource()));
            orgTranslateX = p.getTranslateX();
            orgTranslateY = p.getTranslateY();          
        });
        rect.setOnMouseDragged(event ->
        {
            double offsetX = event.getSceneX() - orgSceneX;
            double offsetY = event.getSceneY() - orgSceneY;
            double newTranslateX = orgTranslateX + offsetX;
            double newTranslateY = orgTranslateY + offsetY;
            Node p = ((Node) (event.getSource()));
            p.setTranslateX(newTranslateX);
            p.setTranslateY(newTranslateY);
            for(Circle circle : Arrays.asList(topLeftHandle, topRightHandle, btmLeftHandle, btmRightHandle))
            {
                circle.setTranslateX(newTranslateX);
                circle.setTranslateY(newTranslateY);
            }
        });
        return rect;
    }
}

你应该看看这个来自karakullukcuhuseyin的好例子-->https://github.com/karakullukcuhuseyin/JavaFX-ImageCropper他还扩展了矩形类,并使用他的自定义矩形来选择图像中的区域。

最新更新