当前位置: 首页 > 知识库问答 >
问题:

JavaFX使用多个FXML文件获取自定义控件

胡墨竹
2023-03-14

我正在尝试使用JavaFX和多个FXML文件中的自定义控件。我创建一个自定义控件:

public class PetListGUIManager extends BorderPane
{
    @FXML ListView<String> petList;

    private PetManager pm;

    public PetListGUIManager() 
    {
        try
        {
           FXMLLoader loader = new  FXMLLoader( getClass().getResource("PetList.fxml"));

           loader.setRoot( this );
           loader.setController( this );

           loader.load();

        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        pm = new PetManager();

        ObservableList<String> items = FXCollections.observableArrayList( pm.getDisplayablePets() );

        petList.setItems( items );
    }

    @FXML
    public void handleButtonAction( ActionEvent event )
    {
        Button b = (Button) event.getSource();
        b.setText("Clicked!");
    }
}

使用此FXML文件:

<fx:root type="javafx.scene.layout.BorderPane" xmlns:fx="http://javafx.com/fxml">
  <bottom>
    <Button onAction="#handleButtonAction" text="Click Me!" />
  </bottom>
  <center>
    <ListView fx:id="petList" prefHeight="200.0" prefWidth="200.0" />
  </center>
</fx:root>

然后我使用另一个主程序:

public class TestMain extends Application
{
    PetListGUIManager pm;
    @FXML FlowPane mainPane;

    @Override
    public void start(Stage stage) throws Exception
    {

        Parent root = FXMLLoader
                .load(getClass().getResource("Main.fxml"));

        Scene scene = new Scene(root);

        stage.setTitle("Test Main");
        stage.setScene(scene);
        stage.show();


       pm = new PetListGUIManager();

    }
    /**
     * Purpose:
     * @param args
     */
    public static void main(String[] args)
    {
        Application.launch( args );
    }

    @FXML
    public void doSomething( ActionEvent ae )
    {
        System.out.println( "In do something: " + mainPane );
        ObservableList<Node> children = mainPane.getChildren( );
        System.out.println( "Children are " + children );
        children.add( pm );

    }
}

使用此FXML文件的:

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="TestMain">
  <children>
    <FlowPane fx:id="mainPane" prefHeight="400.0" prefWidth="600.0" >
    <Button text="Click here to start" onAction="#doSomething"/>
    </FlowPane>
  </children>
</AnchorPane>

当我单击主窗口中的按钮-这应该加载自定义控件我得到一个java.lang.reflect.InvocationTargetExc0019异常引起的:java.lang.NullPointerExcture:儿童:子节点为空:父=FlowPane[id=main Pane]

我错过了什么?

第二个问题:您可能会注意到我在主窗口中任意添加了一个按钮,这样当单击它时,我就可以加载我的BorderPane自定义控件类。理想情况下,我想直接在TestMain的start方法中执行此操作,但main Pane在start方法中为空--它何时变为非空?

共有1个答案

彭衡
2023-03-14

您不应该让您的主应用程序类成为控制器——它太混乱了,充满了您遇到的错误。

当您加载Main.fxml时,fxmloader将创建应用程序类的新实例。当您单击主fxml UI中定义的按钮时,doSomething方法将在新的TestMain对象上调用,而不是在启动应用程序时创建的原始TestMain对象。

解决方案是创建一个MainController.java,作为Main.fxml GUI的控制器(类似于您已经使用PetListGUIManager所做的),并从主应用程序类中完全删除任何与@fxml相关的符号。

 类似资料:
  • 我想创建一个自定义控件,在其中我可以设置另一个自定义控件的列表,并且我想能够像在JavaFXTableView中一样使用FXML(请参见列列表): 我只想写这样的东西: 我已经知道如何实现简单的自定义控件,但我还没有找到任何关于以这种方式组合自定义控件的方法。你能给我指个方向吗?

  • 我正在进行的项目使用的是JavaFx框架,因此我们使用的是fxml文件和场景构建器。我已经为我们的应用程序制作了一个自定义控件,根据我在web上找到的示例,它工作得非常好。但是,我们将有多个带有公共基本功能的自定义控件。因此,我想将基本功能继承到一个自定义控件中。 我正在尝试做的是创建一个扩展自定义根控件类的自定义控件。CustomControl.fxml文件如下所示: 它是皮包骨头,当我打开Cu

  • 我的代码中有以下扩展的JavaFX对象: 它使用我编写的这个客户Java类来跟踪Tile位置: 现在,我想构建一个场景(通过JavaFX场景生成器),它使用一个网格窗格,每个单元格中都有一个平铺对象。我决定首先在scene Builder中构建一个场景,使用JavaFX矩形对象而不是平铺,然后手动编辑.fxml文件并将其中的矩形更改为平铺对象。问题是Intellij现在告诉我FXML文件中的平铺对

  • SpecializedButton FXML视图只创建一个HBox,其中有两个锚窗格,左右两侧分别有一个标签和按钮。单击按钮时,它调用SpecializedButton控制器类中的doSomething()。 问题 通过这个设置,我使用FXML将视图与应用程序逻辑分开。 我会非常感谢你的真知灼见。提前道谢!

  • 转换为fxml 我总是从javafx.fxml.loadException类型中得到错误代码:也许有比创建自定义类更好的解决方案。但我需要一个标签与自定义接口(连接)。也许另一个解决方案是创建一个只包含标签的fxml文件,并通过接口为此设置一个控制器类。 编辑:

  • 我目前正在使用JavaFXML和场景生成器编码一个系统。我已经创建了一个登录页面,您可以登录为管理员或员工。在管理包我有管理。FXML和管理员控制器。 无论如何,我使用了一个TabPane,我有五个选项卡,第一个名为“customers”,所有的实现(代码)都在AdminController中,因为它是AnchorPane的设置根控制器。 正如您所想象的,在一个控制器类中编写这五个选项卡的所有代码