简体   繁体   English

如何通过其 controller class 将 javaFX 形状动态添加到共享窗格?

[英]How do I dynamically add javaFX shapes to a shared pane through its controller class?

I am creating an application which requires a graph consisting of nodes and edges to be displayed.我正在创建一个需要显示由节点和边组成的图形的应用程序。 Each node is represented by a Circle object and each edge is a Line.每个节点由一个 Circle object 表示,每条边是一条 Line。

I have multiple scenes in the application, but the graph needs to be displayed in more than one of these scenes.我在应用程序中有多个场景,但需要在多个场景中显示图形。 So, I have created a fxml file using scene builder which only consists of an anchor pane which I want to be able to display my graph on.因此,我使用场景生成器创建了一个 fxml 文件,该文件仅包含一个我希望能够在其上显示我的图表的锚定窗格。 I have included this fxml file in the other scenes that require the graph to be displayed, so that I can use one controller to add the graph to a single anchor pane which will be shared across many scenes.我已将此 fxml 文件包含在其他需要显示图形的场景中,这样我就可以使用一个 controller 将图形添加到将在多个场景中共享的单个锚窗格。

However, when I add my circles and lines as children to the anchor pane using the controller, they are not visible.但是,当我使用 controller 将我的圆圈和线条作为子级添加到锚定窗格时,它们是不可见的。 Using the debug tool I can see that they are indeed children of the anchor pane, but they are not being displayed.使用调试工具我可以看到它们确实是锚定窗格的子项,但它们没有被显示。 I can see objects that I add to the anchor pane using scene builder (for example, I used scene builder to add a circle to the anchor pane and I could see that when running my GUI, but none of the other children which I added via code).我可以看到我使用场景生成器添加到锚定窗格的对象(例如,我使用场景生成器将一个圆圈添加到锚定窗格,并且在运行我的 GUI 时我可以看到它,但是我添加的其他子项都没有代码)。

To reduce the scope of the problem, I attempted to create a single circle and add it to the anchor pane through my controller class. Despite being a child of the anchor pane, this circle was not visible when running the GUI.为了减少问题的 scope,我尝试创建一个圆圈并通过我的 controller class 将其添加到锚定窗格。尽管是锚定窗格的子级,但在运行 GUI 时这个圆圈是不可见的。

GraphPaneController.java GraphPaneController.java

public class GraphPaneController {
    @FXML Pane paneGraph;
    public void addCircle() {
        
        Circle circle = new Circle();
        circle.setFill(Color.RED);
        circle.setRadius(50);
        circle.setCenterX(0);
        circle.setCenterY(0);
        
        paneGraph.getChildren().add(circle);

    }
}

MainMenuController.java MainMenuController.java

public class MainMenuController {
    public void startButtonClicked() {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("graph_pane.fxml"));
        Parent root = loader.load();
        GraphPaneController gpController = loader.getController();
        controller.addCircle();
        Frontend.setRoot("gamemode_select");
    }
}

Frontend.java前端.java

public class Frontend extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage mainStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("mainmenu.fxml"));
        Scene scene = new Scene(root, 600, 400);
        mainStage.setScene(scene);
        mainStage.show();
    }
    
    public static void setRoot(String fxml) throws IOException {
        newScene.setRoot(loadFXML(fxml));
    }

    public static Parent loadFXML(String fxml) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(Frontend.class.getResource(fxml + ".fxml"));
        return fxmlLoader.load();
    }

}

mainmenu.fxml主菜单.fxml

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="graphvis.group30.MainMenuController">
  <children>
    <AnchorPane id="ap" maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
         <children>
            <ImageView fitHeight="400.0" fitWidth="640.0" opacity="0.19" pickOnBounds="true" />
            <Label layoutX="198.0" layoutY="112.0" text="Graph Colouring Game">
               <font>
                  <Font size="24.0" />
               </font>
            </Label>
            <Button id="btnInputGraphFromFile" layoutX="255.0" layoutY="200.0" mnemonicParsing="false" onAction="#btnInputGraphFromFileClicked" prefHeight="25.0" prefWidth="130.0" text="Input graph from file" />
            <Button id="btnCreateRandomGraph" layoutX="255.0" layoutY="235.0" mnemonicParsing="false" onAction="#btnCreateRandomGraphClicked" text="Create random graph" />
            <Label layoutX="197.0" layoutY="138.0" prefHeight="61.0" prefWidth="245.0" text="Made by Nathan Macdonald, Kasper van der Horst, Oguz Kagan Yarim, Miriam Espinosa, Dorina Sili" textAlignment="CENTER" wrapText="true">
               <font>
                  <Font size="10.0" />
               </font>
            </Label>
            <Button layoutX="255.0" layoutY="269.0" mnemonicParsing="false" onAction="#btnQuitClicked" prefHeight="25.0" prefWidth="130.0" text="Quit" />
         </children>
    </AnchorPane>
  </children>
</VBox>

graph_pane.fxml graph_pane.fxml

<AnchorPane fx:id="paneGraph" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="graphvis.group30.GraphPaneController" />

gamemode_select.fxml游戏模式_select.fxml

<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="graphvis.group30.GamemodeSelectController">
  <children>
    <AnchorPane maxHeight="-1.0" maxWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" VBox.vgrow="ALWAYS">
      <children>
            <fx:include source="graph_pane.fxml" />
            <Label layoutX="139.0" layoutY="14.0" prefHeight="63.0" prefWidth="159.0" text="Select Gamemode:" wrapText="true">
               <font>
                  <Font size="18.0" />
               </font>
            </Label>
            <Button fx:id="btnGamemode1" layoutX="299.0" layoutY="33.0" mnemonicParsing="false" onAction="#btnGamemode1Clicked" text="untill death" />
            <Button fx:id="btnGamemode2" layoutX="384.0" layoutY="33.0" mnemonicParsing="false" onAction="#btnGamemode2Clicked" text="timed" />
            <Button fx:id="btnGamemode3" layoutX="440.0" layoutY="33.0" mnemonicParsing="false" onAction="#btnGamemode3Clicked" text="random " />
            <Button fx:id="btnBack" layoutX="14.0" layoutY="360.0" mnemonicParsing="false" onAction="#btnBackClicked" text="back" />
      </children>
    </AnchorPane>
  </children>
</VBox>

When viewing the gamemode select screen, I expect to see the circle that I added to the graph pane through the GraphPaneController, but it is not there.查看游戏模式 select 屏幕时,我希望看到我通过 GraphPaneController 添加到图形窗格的圆圈,但它不存在。 What do I do so that I can add visual components to a pane which is shared across multiple scenes?我该怎么做才能将视觉组件添加到跨多个场景共享的窗格中?

So I got this to work by creating a model class ( GraphModel ) and a viewer class ( GraphView ) for the graph.因此,我通过为图形创建一个 model class ( GraphModel ) 和一个查看器 class ( GraphView ) 来实现它。 The model class handles creating the vertices and edges, and the viewer class is reponsible for displaying the graph. model class 负责创建顶点和边,查看器 class 负责显示图形。

GraphView extends javafx.scene.layout.Pane and contains an AnchorPane attribute, containing the elements of the graph to be displayed, which can be added to scenes by calling a getAnchorPane method on the GraphView object. GraphView extends javafx.scene.layout.Pane并包含一个AnchorPane属性,包含要显示的图形的元素,可以通过调用GraphView object 上的getAnchorPane方法将其添加到场景中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM