当前位置: 首页 > 面试题库 >

Java FX Rubberband调整大小错误

欧阳俊明
2023-03-14
问题内容

所以,我的橡皮筋课上有一个错误,我似乎无法修复。

我基本上要做的是:我有一个borderpane,它是
我要调整大小的节点的外部窗格。我为该borderpane分配了一个宽度为1
像素的边框(查看CSS)。我还为该边框窗格分配了四个矩形,每个矩形位于一个
角(NE,SE,SW,NW)。在此边框中,我具有所谓的
“ contentPane”。该窗格包含所有内容(矩形,
图像视图等)。

它工作得很好,但是我似乎无法修复错误。

错误:

如果我调整一个像素的大小,则宽度,高度/ x和y会使用
未知值进行调整。之后,调整大小就可以了。在此处输入图片说明

RubberBand2.java

package org.displee.javafx.mod;

import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

/**
 * A class representing a rubberband that can be used to resize panes.
 * @author Displee
 */
public class RubberBand2 {

    /**
     * The parent of this rectangle.
     */
    private final Pane parent;

    /**
     * The rectangle.
     */
    private final Pane node;

    /**
     * The corner rectangles.
     */
    private final Rectangle[] rectangles = new Rectangle[4];

    /**
     * The last known node width.
     */
    private double nodeWidth;

    /**
     * The last known node height.
     */
    private double nodeHeight;

    /**
     * The last known node x-coordinate.
     */
    private double nodeX;

    /**
     * The last known node y-coordinate.
     */
    private double nodeY;

    /**
     * The current selected component.
     */
    public static RubberBand2 SELECTED;

    /**
     * The size of the corners of a rectangle.
     */
    public static final double RECTANGLE_CORNER_SIZE = 5.0;

    /**
     * The minimum width of the {@code node}.
     */
    private static final double MIN_WIDTH = 10.0;

    /**
     * The minimum height of the {@code node}
     */
    private static final double MIN_HEIGHT = 10.0;

    public RubberBand2(Pane node) {
        this.node = node;
        this.parent = (Pane) node.getParent();
        parent.getStyleClass().add("transparent_border");
        createCorners();
        bind();
    }

    /**
     * Create the corners.
     */
    public void createCorners() {
        final Pane inheritPane = node;
        for (int i = 0; i < rectangles.length; i++) {
            final Rectangle rectangle = rectangles[i] = new Rectangle();
            rectangle.setWidth(RECTANGLE_CORNER_SIZE);
            rectangle.setHeight(RECTANGLE_CORNER_SIZE);
            rectangle.setFill(Color.BLACK);
            rectangle.getStyleClass().add("rectangle_corner");
            rectangle.setArcHeight(4);
            rectangle.setArcWidth(4);
            if (i == 0) {
                rectangle.xProperty().bind(inheritPane.layoutXProperty().subtract(RECTANGLE_CORNER_SIZE));
                rectangle.yProperty().bind(inheritPane.layoutYProperty().subtract(RECTANGLE_CORNER_SIZE));
                rectangle.setOnMouseEntered((e) -> {
                    rectangle.setCursor(Cursor.NW_RESIZE);
                });
                rectangle.setOnMouseDragged((event) -> {
                    resize(event, 0);
                });
            } else if (i == 1) {
                rectangle.xProperty().bind(inheritPane.layoutXProperty().add(inheritPane.widthProperty()));
                rectangle.yProperty().bind(inheritPane.layoutYProperty().subtract(RECTANGLE_CORNER_SIZE));
                rectangle.setOnMouseEntered((e) -> {
                    rectangle.setCursor(Cursor.NE_RESIZE);
                });
                rectangle.setOnMouseDragged((event) -> {
                    resize(event, 1);
                });
            } else if (i == 2) {
                rectangle.xProperty().bind(inheritPane.layoutXProperty().add(inheritPane.widthProperty()));
                rectangle.yProperty().bind(inheritPane.layoutYProperty().add(inheritPane.heightProperty()));
                rectangle.setOnMouseEntered((e) -> {
                    rectangle.setCursor(Cursor.SE_RESIZE);
                });
                rectangle.setOnMouseDragged((event) -> {
                    resize(event, 2);
                });
            } else {
                rectangle.xProperty().bind(inheritPane.layoutXProperty().subtract(RECTANGLE_CORNER_SIZE));
                rectangle.yProperty().bind(inheritPane.layoutYProperty().add(inheritPane.heightProperty()));
                rectangle.setOnMouseEntered((e) -> {
                    rectangle.setCursor(Cursor.SW_RESIZE);
                });
                rectangle.setOnMouseDragged((event) -> {
                    resize(event, 3);
                });
            }
            rectangle.setOnMousePressed((e) -> {
                setDefaults();
                e.consume();
            });
            rectangle.setVisible(false);
            parent.getChildren().add(rectangle);
        }
    }

    /**
     * Bind the mouse events.
     */
    public void bind() {
        node.setOnMouseEntered((e) -> {
            node.setCursor(Cursor.MOVE);
        });
        parent.setOnMouseClicked((e) -> {
            if (SELECTED != null) {
                SELECTED.setRubberBandSelection(false);
            }
            SELECTED = this;
            setRubberBandSelection(true);
            e.consume();
        });
        node.setOnMouseClicked((e) -> {
            if (SELECTED != null) {
                SELECTED.setRubberBandSelection(false);
            }
            SELECTED = this;
            setRubberBandSelection(true);
            e.consume();
        });
        node.setOnMousePressed((e) -> {
            setDefaults();
            e.consume();
        });
        node.setOnMouseMoved((e) -> {

        });
        node.setOnMouseReleased((e) -> {

        });
    }

    /**
     * Resize the argued resize type.
     * @param event The mouse event
     * @param type The type (0 = NW, 1 = NE, 2 = SE, 3 = SW);
     */
    public void resize(MouseEvent event, int type) {
        final double mouseX = parent.getBoundsInParent().getMinX() + event.getX();
        final double mouseY = parent.getBoundsInParent().getMinY() + event.getY();
        double newX = nodeX;
        double newY = nodeY;
        double newW = nodeWidth;
        double newH = nodeHeight;
        switch (type) {
        case 0:
            newX = mouseX;
            newY = mouseY;
            newW = nodeWidth + nodeX - newX;
            newH = nodeHeight + nodeY - newY;
            break;
        case 1:
            newY = mouseY;
            newW = mouseX - nodeX;
            newH = nodeHeight + nodeY - newY;
            break;
        case 2:
            newW = mouseX - nodeX;
            newH = mouseY - nodeY;
            break;
        case 3:
            newX = mouseX;
            newW = nodeWidth + nodeX - newX;
            newH = mouseY - nodeY;
            break;
        }
        parent.setLayoutX(newX);
        parent.setLayoutY(newY);
        node.setPrefSize(newW, newH);
    }

    /**
     * Set the defaults before we resize anything.
     */
    public void setDefaults() {
        nodeX = node.getBoundsInParent().getMinX();
        nodeY = node.getBoundsInParent().getMinY();
        nodeHeight = node.getBoundsInParent().getHeight();
        nodeWidth = node.getBoundsInParent().getWidth();
    }

    /**
     * Set the rubber band selection for the rectangle.
     * @param show If we have to show the corner rectangles.
     */
    public void setRubberBandSelection(boolean show) {
        if (show) {
            parent.getStyleClass().remove("transparent_border");
            parent.getStyleClass().add("dotted_pane");
        } else {
            parent.getStyleClass().remove("dotted_pane");
            parent.getStyleClass().add("transparent_border");
        }
        for (Rectangle rectangle : rectangles) {
            rectangle.setVisible(show);
        }
    }

}

style.css

.dotted_pane {
    -fx-background-insets: 0;
    -fx-border-color: white;
    -fx-border-width: 1;
    -fx-border-style: dashed;
}
.transparent_border {
    -fx-background-insets: 0;
    -fx-border-color: transparent;
    -fx-border-width: 1;
    -fx-border-style: solid;
}

Test2.java

package org.test;

import org.displee.javafx.mod.RubberBand2;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Test2 extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        Group root = new Group();
        Scene scene = new Scene(root, 900, 600);
        Pane inner = new Pane();
        inner.setBackground(new Background(new BackgroundFill(Color.web("red"), CornerRadii.EMPTY, Insets.EMPTY)));
        BorderPane border = new BorderPane(inner);
        inner.setPrefSize(100, 100);
        border.setBorder(new Border(new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
        Pane outer = new Pane(border);
        outer.layoutXProperty().bind(scene.widthProperty().divide(4));
        outer.layoutYProperty().bind(scene.heightProperty().divide(4));
        root.getChildren().addAll(outer);
        primaryStage.setScene(scene);
        primaryStage.show();
        new RubberBand2(inner);
    }

}

Any suggestions and improvements are of course much appreciated.

Edit: Sorry, my documentation is pretty outdated xD.

Thanks.


问题答案:

好吧,我找到了解决我问题的廉价方法。

首先,我移动的是边界窗格,而不是自身的节点,因此我
更改了此边界

nodeX = node.getBoundsInParent().getMinX();
nodeY = node.getBoundsInParent().getMinY();

To this

nodeX = parent.getBoundsInParent().getMinX();
nodeY = parent.getBoundsInParent().getMinY();

便宜的修复方法如下:

parent.setLayoutX(newX);
parent.setLayoutY(newY);

我只是根据角落大小增加了newX和newY。这使
一切都完美无瑕。

final double offset = RECTANGLE_CORNER_SIZE - 1;
parent.setLayoutX(newX + offset);
parent.setLayoutY(newY + offset);

我想您可以为自己添加移动矩形和其他调整大小的矩形(N,E,S,W)
,如果没有,我可以为您提供帮助。



 类似资料:
  • 我想创建一个包含一些组件的JInternalFrame。 我的目标是用Java设计一个bash控制台。 我的框架由4个组件组成: 包含在JScrollPane中的JTextArea 带有文本“Cmd:”的JLabel JTextField 带有文本“发送”的JButton 我有以下代码: 因此,当帧未最大化时,我有一个正确的外观: 但当我将其最大化时,所有组件的位置都不正确: 因此,我的问题是:如

  • 我正在尝试构建一个包含6个窗格(作为父级添加到GridPane布局中)的简单Java项目。我必须在开始时设置窗口大小,并通过参考根布局的宽度和高度,设法将它们均匀地拆分。 但我想要他们调整大小,因为我改变了窗口的大小(使用鼠标,现在他们得到固定的大小)。 下面是我的代码:

  • 问题内容: 我一直试图(徒劳地)建立一个页面,当我更改窗口大小时,其元素将重新调整大小。我可以在CSS中使用它来处理图像,但是没有问题,但是我似乎无法在文本上完成相同的操作,而且我不确定在CSS中是否有可能。而且我似乎找不到能完成此任务的jQuery脚本。 当用户调整窗口大小时,我实质上希望页面能够动态流畅地缩放,而无需用户调用页面缩放。通过css在我的img div上这可以正常工作,但对于文本则

  • 问题内容: 下面的代码调整位图的大小并保持宽高比。我想知道是否有一种更有效的大小调整方法,因为我想到了我正在编写android API中已经可用的代码。 问题答案: 使用方法:)

  • 问题内容: 当前版本的Firefox和Chrome包含一个拖动处理程序以调整框的大小。我需要捕获调整大小的事件,我认为使用jQuery的事件会很容易,但是它不起作用! 有没有办法捕获它? 问题答案: Chrome不会捕获resize事件,Chrome不会捕获mousedown,因此您需要设置init状态,然后通过mouseup处理更改: HTML 注意: 您可以像侯赛因所做的那样附加自己可调整大小

  • 问题内容: 我在这里使用Go调整大小包:https://github.com/nfnt/resize 我正在从S3中提取图像,如下所示: // this gives me data []byte 之后,我需要调整图像大小: // problem is that the original_image has to be of type image.Image 将图像上传到我的S3存储桶 // pro