如何将 FXML 加载到 class 实例中?
How to load FXML in to a class instance?
我需要将 fxml 表单加载到 class 对象并对其进行操作。
可能吗 ?目前我正在尝试这样做:
<?xml version = "1.0" encoding = "UTF-8" ?>
<!-- imports -->
<?import javafx.geometry.Insets ?>
<?import javafx.scene.control.Label ?>
<?import javafx.scene.text.Font ?>
<?import org.bsoftware.parcel.domain.components.LogItem ?>
<!-- layout -->
<LogItem spacing = "3" xmlns:fx = "http://javafx.com/fxml" >
<padding>
<Insets bottom = "2" left = "5" right = "5" top = "2" />
</padding>
<Label fx:id = "labelTimestamp">
<font>
<Font name = "System Bold" size = "11" />
</font>
</Label>
<Label fx:id = "labelMessage">
<font>
<Font name = "System Italic" size = "11" />
</font>
</Label>
</LogItem>
@Getter
public class LogItem extends HBox
{
@FXML
private Label labelTimestamp;
@FXML
private Label labelMessage;
}
我正在尝试像这样访问它
final LogItem logItem = FXMLLoader.load(Objects.requireNonNull(LogView.class.getResource("/fxml/components/log_item.fxml")));
但在这里我总是得到 null pionter exeption
logItem.getLabelTimestamp()
使用 fx:root
中记录的结构:
示例应用程序
实施说明:
- 使用
fx:root
构造 link FXML 加载节点到 Java 对象。
- 添加 CSS 文件以将样式与布局分开。
- 应用 MVC 模式,从视图对象 (
LogItemView
) 中抽象出模型对象 (LogItem
)。
- 在视图中封装视图元素(节点),而不是通过 API.
公开它们
- 将 LogItem 公开为 LogItemView 的 属性,以便可以直接查询日志项的数据,并在必要时在视图中替换。
- 为不可变的 read-only LogItem 而不是 Lombok 使用记录。
- 使用 Instant 表示时间。
- 使用日期格式化程序将即时格式化为默认时区中的日期字符串。
- 如果与视图关联的 logitem 属性 发生更改,则使用更改侦听器刷新视图。
module-info.java
module com.example.logdemo {
requires javafx.controls;
requires javafx.fxml;
opens com.example.logdemo to javafx.fxml;
exports com.example.logdemo;
}
LogApplication.java
package com.example.logdemo;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.time.Instant;
public class LogApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
LogItemView logItemView = new LogItemView();
logItemView.setLogItem(
new LogItem(Instant.now(), "hello, world")
);
stage.setScene(new Scene(logItemView));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
LogItem.java
package com.example.logdemo;
import java.time.Instant;
public record LogItem(
Instant timestamp,
String message
) {}
LogItemView.java
package com.example.logdemo;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import java.io.IOException;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class LogItemView extends HBox {
@FXML
private Label timestamp;
@FXML
private Label message;
private final ObjectProperty<LogItem> logItem = new SimpleObjectProperty<>();
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withZone(ZoneId.systemDefault());
public LogItemView() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(
LogItemView.class.getResource(
"log-item.fxml"
)
);
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
fxmlLoader.load();
logItem.addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
timestamp.setText(null);
message.setText(null);
} else {
timestamp.setText(
formatter.format(
logItem.getValue().timestamp()
)
);
message.setText(
logItem.getValue().message()
);
}
});
}
public LogItem getLogItem() {
return logItem.get();
}
public void setLogItem(LogItem logItem) {
this.logItem.set(logItem);
}
public ObjectProperty<LogItem> logItemProperty() {
return logItem;
}
}
log-item.fxml
<?xml version = "1.0" encoding = "UTF-8" ?>
<?import javafx.scene.control.Label ?>
<?import com.example.logdemo.LogItemView?>
<?import java.net.URL?>
<fx:root type="com.example.logdemo.LogItemView" styleClass="log-item" xmlns:fx = "http://javafx.com/fxml">
<Label fx:id = "timestamp" styleClass="timestamp"/>
<Label fx:id = "message" styleClass="message"/>
<stylesheets>
<URL value="@log-item.css" />
</stylesheets>
</fx:root>
log-item.css
.log-item {
-fx-padding: 2px 5px 2px 5px;
-fx-spacing: 8px;
-fx-font-family: monospace;
-fx-font-size: 15px;
}
.log-item > .timestamp {
-fx-font-weight: bold;
}
.log-item > .message {
-fx-font-style: italic;
}
我需要将 fxml 表单加载到 class 对象并对其进行操作。 可能吗 ?目前我正在尝试这样做:
<?xml version = "1.0" encoding = "UTF-8" ?>
<!-- imports -->
<?import javafx.geometry.Insets ?>
<?import javafx.scene.control.Label ?>
<?import javafx.scene.text.Font ?>
<?import org.bsoftware.parcel.domain.components.LogItem ?>
<!-- layout -->
<LogItem spacing = "3" xmlns:fx = "http://javafx.com/fxml" >
<padding>
<Insets bottom = "2" left = "5" right = "5" top = "2" />
</padding>
<Label fx:id = "labelTimestamp">
<font>
<Font name = "System Bold" size = "11" />
</font>
</Label>
<Label fx:id = "labelMessage">
<font>
<Font name = "System Italic" size = "11" />
</font>
</Label>
</LogItem>
@Getter
public class LogItem extends HBox
{
@FXML
private Label labelTimestamp;
@FXML
private Label labelMessage;
}
我正在尝试像这样访问它
final LogItem logItem = FXMLLoader.load(Objects.requireNonNull(LogView.class.getResource("/fxml/components/log_item.fxml")));
但在这里我总是得到 null pionter exeption
logItem.getLabelTimestamp()
使用 fx:root
中记录的结构:
示例应用程序
实施说明:
- 使用
fx:root
构造 link FXML 加载节点到 Java 对象。 - 添加 CSS 文件以将样式与布局分开。
- 应用 MVC 模式,从视图对象 (
LogItemView
) 中抽象出模型对象 (LogItem
)。 - 在视图中封装视图元素(节点),而不是通过 API. 公开它们
- 将 LogItem 公开为 LogItemView 的 属性,以便可以直接查询日志项的数据,并在必要时在视图中替换。
- 为不可变的 read-only LogItem 而不是 Lombok 使用记录。
- 使用 Instant 表示时间。
- 使用日期格式化程序将即时格式化为默认时区中的日期字符串。
- 如果与视图关联的 logitem 属性 发生更改,则使用更改侦听器刷新视图。
module-info.java
module com.example.logdemo {
requires javafx.controls;
requires javafx.fxml;
opens com.example.logdemo to javafx.fxml;
exports com.example.logdemo;
}
LogApplication.java
package com.example.logdemo;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.time.Instant;
public class LogApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
LogItemView logItemView = new LogItemView();
logItemView.setLogItem(
new LogItem(Instant.now(), "hello, world")
);
stage.setScene(new Scene(logItemView));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
LogItem.java
package com.example.logdemo;
import java.time.Instant;
public record LogItem(
Instant timestamp,
String message
) {}
LogItemView.java
package com.example.logdemo;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import java.io.IOException;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
public class LogItemView extends HBox {
@FXML
private Label timestamp;
@FXML
private Label message;
private final ObjectProperty<LogItem> logItem = new SimpleObjectProperty<>();
private static final DateTimeFormatter formatter =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withZone(ZoneId.systemDefault());
public LogItemView() throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(
LogItemView.class.getResource(
"log-item.fxml"
)
);
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
fxmlLoader.load();
logItem.addListener((observable, oldValue, newValue) -> {
if (newValue == null) {
timestamp.setText(null);
message.setText(null);
} else {
timestamp.setText(
formatter.format(
logItem.getValue().timestamp()
)
);
message.setText(
logItem.getValue().message()
);
}
});
}
public LogItem getLogItem() {
return logItem.get();
}
public void setLogItem(LogItem logItem) {
this.logItem.set(logItem);
}
public ObjectProperty<LogItem> logItemProperty() {
return logItem;
}
}
log-item.fxml
<?xml version = "1.0" encoding = "UTF-8" ?>
<?import javafx.scene.control.Label ?>
<?import com.example.logdemo.LogItemView?>
<?import java.net.URL?>
<fx:root type="com.example.logdemo.LogItemView" styleClass="log-item" xmlns:fx = "http://javafx.com/fxml">
<Label fx:id = "timestamp" styleClass="timestamp"/>
<Label fx:id = "message" styleClass="message"/>
<stylesheets>
<URL value="@log-item.css" />
</stylesheets>
</fx:root>
log-item.css
.log-item {
-fx-padding: 2px 5px 2px 5px;
-fx-spacing: 8px;
-fx-font-family: monospace;
-fx-font-size: 15px;
}
.log-item > .timestamp {
-fx-font-weight: bold;
}
.log-item > .message {
-fx-font-style: italic;
}