我的代码中有以下扩展的JavaFX对象:
package shipsinspace.view.board;
import javafx.scene.shape.Rectangle;
import shipsinspace.common.Coordinates;
public class Tile extends Rectangle {
private Coordinates coordinates;
public Tile(double width, double height, Coordinates coordinates) {
super(width, height);
this.coordinates = coordinates;
}
public Coordinates getCoordinates() {
return coordinates;
}
}
它使用我编写的这个客户Java类来跟踪Tile位置:
package shipsinspace.common;
import java.util.Objects;
public class Coordinates {
private int xCoordinate;
private int yCoordinate;
public Coordinates(int xCoordinate, int yCoordinate) {
this(xCoordinate, yCoordinate, 10, false);
}
public Coordinates(int xCoordinate, int yCoordinate, int max) {
this(xCoordinate, yCoordinate, max, false);
}
public Coordinates(int xCoordinate, int yCoordinate, int max, boolean allowedZero) {
if (allowedZero) {
if ((xCoordinate >= 0 && yCoordinate >= 0) && (xCoordinate <= max && yCoordinate <= max)) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
} else {
throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
}
} else {
if ((xCoordinate > 0 && yCoordinate > 0) && (xCoordinate <= max && yCoordinate <= max)) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
} else {
throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
}
}
}
public int getX() {
return xCoordinate;
}
public int getY() {
return yCoordinate;
}
public Coordinates returnNeighbour(int axis, int direction) {
if (axis == 0) {
try {
return new Coordinates(this.getX() + direction, this.getY());
} catch (IllegalArgumentException e) {
return new Coordinates(this.getX(), this.getY());
}
} else {
try {
return new Coordinates(this.getX(), this.getY() + direction);
} catch (IllegalArgumentException e) {
return new Coordinates(this.getX(), this.getY());
}
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinates that = (Coordinates) o;
return xCoordinate == that.xCoordinate &&
yCoordinate == that.yCoordinate;
}
@Override
public int hashCode() {
return Objects.hash(xCoordinate, yCoordinate);
}
@Override
public String toString() {
return String.format("Coordinates (%d, %d)", xCoordinate, yCoordinate);
}
}
现在,我想构建一个场景(通过JavaFX场景生成器),它使用一个网格窗格,每个单元格中都有一个平铺对象。我决定首先在scene Builder中构建一个场景,使用JavaFX矩形对象而不是平铺,然后手动编辑.fxml文件并将其中的矩形更改为平铺对象。问题是Intellij现在告诉我FXML文件中的平铺对象无法实例化:
...
<center>
<GridPane BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Tile arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="52.0" stroke="BLACK" strokeType="INSIDE" width="53.0" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
<GridPane.margin>
<Insets bottom="1.0" left="1.0" right="1.0" top="1.0" />
</GridPane.margin>
</Tile>
...
我可以看出,这是因为我的Tile对象需要将坐标对象传递到其构造函数中,而不是高度和宽度,但我无法确定如何将它们粘贴到FXML代码中。任何帮助都将不胜感激。
您可以通过Java代码添加组件。
用代码命名要访问的组件。
public class App {
@FXML GridPane examplePane;
public void initialize() {
Tile t = new Tile();
examplePane.add(t);
...
}
}
要允许FXMLLoader
实例化没有无参数构造函数的类,您需要注释构造函数参数。(这样做的原因是Java参数名称不能保证在运行时保留,因此需要一种机制来反射地将无序值与运行时基于名称的参数匹配。)请参见javaFX 8中@NamedArg注释的目的是什么?了解更多信息。
因此,您的平铺
和坐标
类现在看起来像:
import javafx.beans.NamedArg;
import javafx.scene.shape.Rectangle;
public class Tile extends Rectangle {
private Coordinates coordinates;
public Tile(
@NamedArg("width") double width,
@NamedArg("height") double height,
@NamedArg("coordinates") Coordinates coordinates) {
super(width, height);
this.coordinates = coordinates;
}
public Coordinates getCoordinates() {
return coordinates;
}
}
import java.util.Objects;
import javafx.beans.NamedArg;
public class Coordinates {
private int xCoordinate;
private int yCoordinate;
public Coordinates(
@NamedArg("xCoordinate") int xCoordinate,
@NamedArg("yCoordinate") int yCoordinate) {
this(xCoordinate, yCoordinate, 10, false);
}
public Coordinates(
@NamedArg("xCoordinate") int xCoordinate,
@NamedArg("yCoordinate") int yCoordinate,
@NamedArg("max") int max) {
this(xCoordinate, yCoordinate, max, false);
}
public Coordinates(
@NamedArg("xCoordinate") int xCoordinate,
@NamedArg("yCoordinate") int yCoordinate,
@NamedArg("max") int max,
@NamedArg("allowedZero") boolean allowedZero) {
if (allowedZero) {
if ((xCoordinate >= 0 && yCoordinate >= 0) && (xCoordinate <= max && yCoordinate <= max)) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
} else {
throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
}
} else {
if ((xCoordinate > 0 && yCoordinate > 0) && (xCoordinate <= max && yCoordinate <= max)) {
this.xCoordinate = xCoordinate;
this.yCoordinate = yCoordinate;
} else {
throw new IllegalArgumentException(String.format("Either X or Y has set to value <= 0, or > %d", max));
}
}
}
// remaining code unaltered...
}
要在FXML中使用它,可以执行以下操作:
<Tile width="100.0" height="100.0">
<coordinates>
<Coordinates xCoordinate="1" yCoordinate="1"/>
</coordinates>
</Tile>
或者
<fx:define>
<Coordinates fx:id="tileCoordinates" xCoordinate="1" yCoordinate="1" />
</fx:define>
<Tile width="100.0" height="100.0" coordinates="$tileCoordinates" />
这两者之间的选择大多只是风格的选择;然而请注意,后一种选项为多个Tile
提供了共享相同坐标
实例的机会(可能不适用于此特定用例,但一般来说它可以是有用的)。
转换为fxml 我总是从javafx.fxml.loadException类型中得到错误代码:也许有比创建自定义类更好的解决方案。但我需要一个标签与自定义接口(连接)。也许另一个解决方案是创建一个只包含标签的fxml文件,并通过接口为此设置一个控制器类。 编辑:
我正在尝试使用JavaFX和多个FXML文件中的自定义控件。我创建一个自定义控件: 使用此FXML文件: 然后我使用另一个主程序: 使用此FXML文件的: 当我单击主窗口中的按钮-这应该加载自定义控件我得到一个java.lang.reflect.InvocationTargetExc0019异常引起的:java.lang.NullPointerExcture:儿童:子节点为空:父=FlowPane
我想创建一个自定义控件,在其中我可以设置另一个自定义控件的列表,并且我想能够像在JavaFXTableView中一样使用FXML(请参见列列表): 我只想写这样的东西: 我已经知道如何实现简单的自定义控件,但我还没有找到任何关于以这种方式组合自定义控件的方法。你能给我指个方向吗?
SpecializedButton FXML视图只创建一个HBox,其中有两个锚窗格,左右两侧分别有一个标签和按钮。单击按钮时,它调用SpecializedButton控制器类中的doSomething()。 问题 通过这个设置,我使用FXML将视图与应用程序逻辑分开。 我会非常感谢你的真知灼见。提前道谢!
我正在学习编写用于JavaFX8和Scene Builder的FXML自定义组件。 我编写了如下所示的FXML文件,但Scene Builder不会打开它,由于出现异常,给出消息“open operation has Failed”:
我有一个FXML文档,其中包含我的JavaFX项目的视觉基础,我想通过使用一个窗格来创建一个自己的Topbar(X、最小值/最大值等等)。但我的程序将有多个页面(场景),为了保持代码干净,我想将自定义Topbar作为一个单独的类(有点像组件对象)。我只是不知道该如何在我使用的FXML基础上实现这个类(我使用的是Scene Builder)。