我是Java FX的新手,正在创建一个有趣的应用程序。我试图动态添加TitledPane
,并且在尝试查找TitledPane
的标题时大约70%的时间都会获得空指针异常。我尝试创建一个简单的演示我的问题,但无法重现我的应用程序之外的问题,但我可以解决我的问题。我希望有人能帮助我理解为什么我的解决方案有效,并且可能会指出我更好的解决方案。我正在使用带控制器的FXML文件。我正在尝试在Platform.runLater()中查找标题,因为我手动编辑标题的布局和元素。在Controller的初始化函数内部,我执行以下操作以获取空指针异常:
Platform.runLater(new Runnable() {
@Override
public void run() {
titledpane.lookup(".title"); // will return null about 70% of the time
}
});
// Do more stuff
但是,如果我将该调用包装在一个定时器中并在500毫秒内执行它,它似乎永远不会返回Null。
new java.util.Timer().schedule(new java.util.TimerTask() {
@Override
public void run() {
Platform.runLater(new Runnable() {
@Override
public void run() {
titledpane.lookup(".title"); // doesn't seem to return null
}
});
}
}, 500);
一个论坛提到在调用标题上的查找之前必须将CSS应用于该元素,因此我尝试手动将CSS应用于标题,但titledpane.lookup(".title")
仍然返回null。任何人都可以帮我理解这里发生的事情吗?提前谢谢!
答案 0 :(得分:1)
我有同样的问题。我通过在包含applyCss()
的窗格上调用layout()
和TitledPane
来解决此问题:
Node loadedPane = paneLoader.load();
bodyPane.setCenter(loadedPane);
bodyPane.applyCss();
bodyPane.layout();
答案 1 :(得分:0)
您应该阅读文章Creating a Custom Control with FXML。
以下是有关如何动态加载TitledPane的示例。每次单击“添加任务”按钮时都会添加TitledPane。
Task.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.effect.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<fx:root collapsible="false" prefHeight="72.0" prefWidth="202.0" text="Task" type="TitledPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<content>
<Pane prefHeight="43.0" prefWidth="200.0">
<children>
</children>
</Pane>
</content>
</fx:root>
Task.java
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.Region;
public class Task extends Region {
TitledPane titledPane;
public Task( String title) {
final FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource( "Task.fxml"));
titledPane = new TitledPane();
fxmlLoader.setRoot( titledPane);
fxmlLoader.setController( this);
try {
fxmlLoader.load();
} catch( IOException exception) {
throw new RuntimeException( exception);
}
titledPane.setText(title);
getChildren().add( titledPane);
}
}
Demo.java
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class Demo extends Application {
@Override
public void start(Stage primaryStage) {
Group root = new Group();
Button addTaskButton = new Button( "Add Task");
addTaskButton.setOnAction(new EventHandler<ActionEvent>() {
double x=0;
double y=0;
int count=0;
@Override
public void handle(ActionEvent event) {
// calculate new position
x+=50;
y+=50;
// task counter
count++;
Task task = new Task( "Task " + count);
task.relocate(x, y);
root.getChildren().add( task);
}
});
root.getChildren().add( addTaskButton);
Scene scene = new Scene( root, 1024, 768);
primaryStage.setScene( scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
截图:
为了创建自定义标题,有各种解决方案。这是一个。注意:您需要在正确的路径中提供图标或调整路径。或者,您可以禁用ImageView节点,而是使用Rectangle进行演示。它只是显示的另一个节点。
public class Task extends Region {
TitledPane titledPane;
public Task( String title) {
final FXMLLoader fxmlLoader = new FXMLLoader( getClass().getResource( "Task.fxml"));
titledPane = new TitledPane();
fxmlLoader.setRoot( titledPane);
fxmlLoader.setController( this);
try {
fxmlLoader.load();
} catch( IOException exception) {
throw new RuntimeException( exception);
}
// create custom title with text left and icon right
AnchorPane anchorpane = new AnchorPane();
double offsetRight = 20; // just an arbitrary value. usually the offset from the left of the title
anchorpane.prefWidthProperty().bind(titledPane.widthProperty().subtract( offsetRight));
// create text for title
Label label = new Label( title);
// create icon for title
Image image = new Image( getClass().getResource( "title.png").toExternalForm());
ImageView icon = new ImageView();
icon.setImage(image);
// Rectangle icon = new Rectangle(16, 16);
// set text and icon positions
AnchorPane.setLeftAnchor(label, 0.0);
AnchorPane.setRightAnchor(icon, 0.0);
// add text and icon to custom title
anchorpane.getChildren().addAll( label, icon);
// set custom title
titledPane.setGraphic( anchorpane);
// show only our custom title, don't show the text of titlePane
titledPane.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
getChildren().add( titledPane);
}
}