我正在尝试编写一个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);
}
}
答案 0 :(得分:2)
现在查看updateGUI
的内部。您正在呼叫graphics.fillRect
,但正在设置graphics.setStroke
。笔触和填充是不同的属性,如果要填充,请用所需的setFill
调用Paint
,如果要描边,请调用setStroke
。另外,您需要在执行绘制操作之前 而不是之后设置笔划/填充。
关于检查交叉点,请查看Shape#intersect
或Node.intersects
。第一个返回的形状是相交的结果,并且适用于所有形状。第二个返回的是布尔值,具体取决于节点的矩形边界,因此它仅对矩形是正确的。
此外,请记住在每次绘制前都需要清除画布。
答案 1 :(得分:2)
在运行此代码时,您没有提到得到NullPointerException
,请始终包括此类信息并包括堆栈跟踪。
获得NPE的原因是因为从未设置Rectangles
类字段height1Text
等。而是在代码中使用相同的名称声明局部变量,而不是分配类字段。
修复该问题后,NPE消失。
第二,在使用fill
时,矩形需要使用fillRect
颜色,因此请务必进行设置。除非您使用stroke
,否则drawRect
颜色不会帮助您。另外,请先设置所需的颜色(使用setFill
,然后调用fillRect
,而不是相反。