按钮按下JavaFX时在textField中绘制具有尺寸的矩形并查找它们是否相交

时间:2019-05-09 02:46:53

标签: java user-interface javafx canvas

我正在尝试编写一个JavaFX程序,该程序使用TextField框从用户那里获取尺寸,并创建两个矩形,绘制它们,并在它们相交时发送消息。我在绘制矩形时遇到了麻烦,但我不知道为什么会这样。我也不确定在查看值时如何分辨它们是否相交。您可以提供的任何帮助将不胜感激,我已在下面发布了我的代码。

我的代码:

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.scene.layout.StackPane;
import javafx.geometry.Insets;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.control.*;
import javafx.scene.shape.Rectangle;
public class Rectangles extends Application
{
    Canvas canvas;
    Label intersectLabel;
    TextField x1Text;
    TextField x2Text;
    TextField y1Text;
    TextField y2Text;
    TextField width1Text;
    TextField width2Text;
    TextField height1Text;
    TextField height2Text;

    @Override
    public void start(Stage stage) throws Exception
    {
        // Create a VBox to stack panes vertically
        VBox panesStack = new VBox(20);
        // Create padding of 10 pixels
        Insets padding = new Insets(10);

        // Create labels and text fields for rectangle 1 info
        Label x1Label = new Label("X:");
        // Create labels and field for r1.
        TextField x1Text = new TextField();
        Label y1Label = new Label("Y:");
        TextField y1Text = new TextField();
        Label width1Label = new Label("Width:");
        TextField width1Text = new TextField();
        Label height1Label = new Label("Height:");
        TextField height1Text = new TextField();

        // Create grid pane for rectangle 1 info, set spacing
        GridPane grid1 = new GridPane();
        grid1.setPadding(padding);
        grid1.setHgap(10);
        grid1.setVgap(5);

        // Add rectangle 1 labels and text fields to grid pane
        // First add the top label to span two columns
        grid1.add(new Label("Enter Rectangle 1 info:"),0,0,2,1);
        grid1.add(x1Label,0,1);
        // Add rest of labels and text fields to grid pane
        grid1.add(x1Text,1,1);
        grid1.add(y1Label,0,2);
        grid1.add(y1Text,1,2);
        grid1.add(width1Label,0,3);
        grid1.add(width1Text,1,3);
        grid1.add(height1Label,0,4);
        grid1.add(height1Text,1,4);

        // Create labels and text fields for rectangle 2 info
        Label x2Label = new Label("X:");
        TextField x2Text = new TextField();
        Label y2Label = new Label("Y:");
        TextField y2Text = new TextField();
        Label width2Label = new Label("Width:");
        TextField width2Text = new TextField();
        Label height2Label = new Label("Height:");
        TextField height2Text = new TextField();

        // Create grid pane for rectangle 2 info, set spacing
        GridPane grid2 = new GridPane();
        grid2.setPadding(padding);
        grid2.setHgap(10);
        grid2.setVgap(5);

        // Add rectangle 2 labels and text fields to grid pane
        // First add the top label to span two columns
        grid2.add(new Label("Enter Rectangle 2 info:"),0,0,2,1);
        // Add field and labels
        grid2.add(x2Label,0,1);
        grid2.add(x2Text,1,1);
        grid2.add(y2Label,0,2);
        grid2.add(y2Text,1,2);
        grid2.add(width2Label,0,3);
        grid2.add(width2Text,1,3);
        grid2.add(height2Label,0,4);
        grid2.add(height2Text,1,4);

        // Add the two rectangle info grid panes to an HBox
        // (so they appear horizontally)
        // then add the HBox to the overarching vertical box (panesStack)
        HBox rectGrids = new HBox(30);
        rectGrids.getChildren().add(grid1);
        rectGrids.getChildren().add(grid2);
        panesStack.getChildren().add(rectGrids);

        // Create update button
        // Add event handler to button
        // Add it to overarching vertical box (panesStack)
        Button update = new Button("Update");
        update.setOnAction(this::updateGUI);
        panesStack.getChildren().add(new StackPane(update));

        // Create a canvas for drawing the rectangles
        canvas = new Canvas(600, 500);      
        // Get the canvas' graphics context to draw
        GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
        // Initially make the canvas blank white
        graphicsContext.setFill(Color.WHITE);
        graphicsContext.fillRect(0,0, canvas.getWidth(), canvas.getHeight());

        // Add the canvas to the overarching vertical box (panesStack)
        panesStack.getChildren().add(canvas);

        // Create a label for the intersection message
        intersectLabel = new Label("waiting for rectangle info");
        intersectLabel.setPadding(new Insets(0,0,20,0));
        panesStack.getChildren().add(new StackPane(intersectLabel));

        // Create a scene containing the overarching vertical box
        Scene scene = new Scene(panesStack);             
        stage.setTitle("Rectangles Lab"); // Set window's title
        stage.setScene(scene);            // Set window's scene
        stage.show();
    }
    public void updateGUI(ActionEvent e) {
        Rectangle r1 = new Rectangle();
        r1.setHeight(Double.valueOf(height1Text.getText()));
        r1.setWidth(Double.valueOf(width1Text.getText()));
        r1.setX(Double.valueOf(x1Text.getText()));
        r1.setY(Double.valueOf(y1Text.getText()));

        Rectangle r2 = new Rectangle();
        r2.setHeight(Double.valueOf(height2Text.getText()));
        r2.setWidth(Double.valueOf(width2Text.getText()));
        r2.setX(Double.valueOf(x2Text.getText()));
        r2.setY(Double.valueOf(y2Text.getText()));

        GraphicsContext graphics = canvas.getGraphicsContext2D();
        graphics.fillRect(r1.getX(), r1.getY(), r1.getWidth(), r1.getHeight());
        graphics.setStroke(Color.BLUE);

        graphics.fillRect(r2.getX(), r2.getY(), r2.getWidth(), r2.getHeight());
        graphics.setStroke(Color.RED);

    }
}

2 个答案:

答案 0 :(得分:2)

首先,修复由于NPE而导致的shadowing

现在查看updateGUI的内部。您正在呼叫graphics.fillRect,但正在设置graphics.setStroke。笔触和填充是不同的属性,如果要填充,请用所需的setFill调用Paint,如果要描边,请调用setStroke。另外,您需要在执行绘制操作之前 而不是之后设置笔划/填充。

关于检查交叉点,请查看Shape#intersectNode.intersects。第一个返回的形状是相交的结果,并且适用于所有形状。第二个返回的是布尔值,具体取决于节点的矩形边界,因此它仅对矩形是正确的。

此外,请记住在每次绘制前都需要清除画布。

答案 1 :(得分:2)

在运行此代码时,您没有提到得到NullPointerException,请始终包括此类信息并包括堆栈跟踪。

获得NPE的原因是因为从未设置Rectangles类字段height1Text等。而是在代码中使用相同的名称声明局部变量,而不是分配类字段。

修复该问题后,NPE消失。

第二,在使用fill时,矩形需要使用fillRect颜色,因此请务必进行设置。除非您使用stroke,否则drawRect颜色不会帮助您。另外,请先设置所需的颜色(使用setFill,然后调用fillRect,而不是相反。