JavaFX TitledPane查找(.title)返回null

时间:2015-01-06 06:54:36

标签: java javafx

我是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。任何人都可以帮我理解这里发生的事情吗?提前谢谢!

2 个答案:

答案 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);
    }

}

截图:

enter image description here

为了创建自定义标题,有各种解决方案。这是一个。注意:您需要在正确的路径中提供图标或调整路径。或者,您可以禁用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);

    }

}

enter image description here