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

在JavaFX中动态添加节点

瞿文柏
2023-03-14

我正在尝试构建一个在JavaFX中实现群聊的聊天应用程序。我想在边框窗格内创建一个滚动窗格,该窗格将包含用户所属的所有组。当用户加入时,需要将组图标(ImageViews)动态添加(在场景生成器中无法完成)到滚动窗格(在HBox内)。

目前,我正在使用一个SceneController类,该类负责所有阶段和场景更改。

package com.ong.Controllers;

import com.ong.Main;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.HashMap;

public class ScreenController {
    private static HashMap<String, Scene> screenMap = new HashMap<>();
    private static Stage main;

    public ScreenController(Stage _main){
        main = _main;
    }

    public static void addScreen(String name, FXMLLoader fxmlLoader){
        Scene scene = null;
        try {
            scene = new Scene(fxmlLoader.load());
        } catch (IOException e) {
            e.printStackTrace();
        }
        screenMap.put(name,scene);
    }

    public static void addScene(String name, Scene scene){
        screenMap.put(name,scene);
    }

    public static void removeScreen(String name){
        screenMap.remove(name);
    }

    public static void setMinimumDimensions(int width, int height){
        main.setMinWidth(width);
        main.setMinHeight(height);
    }

    public static void setMaximized(boolean full){
        main.setMaximized(full);
    }

    public static void activate(String name){
        main.setScene(screenMap.get(name));
        main.getIcons().add(new Image(Main.class.getResource("Images/not_logo.png").toString()));
        main.setTitle(name);
        main.show();
    }
}

我已经创建了一个FXML文件(使用场景生成器),其中包含一个边框窗格和一个滚动窗格作为顶层子级。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<BorderPane fx:id="borderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/11.0.2" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.ong.Controllers.HomepageController">
   <top>
      <ScrollPane fx:id="groupsMenuScrollPane" hbarPolicy="NEVER" prefHeight="62.0" prefWidth="1920.0" stylesheets="@../CSS/groups_menu.css" vbarPolicy="NEVER" BorderPane.alignment="CENTER" />
   </top>
</BorderPane>

我的计划是将所有组(初始化时)填充到页面控制器的滚动窗格中。

package com.ong.Controllers;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.shape.Circle;

import java.net.URL;
import java.util.ResourceBundle;

public class HomepageController implements Initializable {

    @FXML
    private ScrollPane groupsMenuScrollPane;

    @FXML
    private BorderPane borderPane;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        final ImageView imageView = new ImageView("com/ong/Images/not_logo.png");
        final Circle clip = new Circle(300, 200, 200);
        imageView.setClip(clip);

        HBox hbox = new HBox();
        hbox.getChildren().add(imageView);

        groupsMenuScrollPane.setContent(hbox);
        borderPane.setTop(groupsMenuScrollPane);

        Scene scene = new Scene(borderPane);

        ScreenController.addScene("Homepage", scene);
        ScreenController.activate("Homepage");
    }
}

我已经尝试使用更新的边框窗格创建场景,但是我得到一个错误“边框窗格已经设置为另一个场景的根”。我还试图直接更改已经存在的场景的根,但是在这种情况下我得到一个NullPointerException。

您能告诉我哪种方式是将节点动态添加到滚动窗格的最佳方式吗。我也将非常感谢您对项目结构的评论。

共有2个答案

慕容玉书
2023-03-14

你的问题和问题是分开的。

谢谢你的提问。动态添加您想要查看ListView的元素。https://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/ListView.html

类似于用于javafx的recyclerview或可重用视图的任何内容

至于你的问题。场景只能有一个根节点。在此根中,您应该有您的边界窗格,其中应该是您的ListView。

周玺
2023-03-14

您能否建议将节点动态添加到滚动窗格的最佳方式。

您需要一个对滚动窗格(本例中为HBox)内容的引用,以及向其中添加内容的方法:

public class HomepageController implements Initializable {

    @FXML
    private ScrollPane groupsMenuScrollPane;

    @FXML
    private BorderPane borderPane;

    private HBox groupContainer ;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        final ImageView imageView = new ImageView("com/ong/Images/not_logo.png");
        final Circle clip = new Circle(300, 200, 200);
        imageView.setClip(clip);

        groupContainer = new HBox();
        groupContainer.getChildren().add(imageView);

        groupsMenuScrollPane.setContent(groupContainer);

        // this is not needed since it's already done in FXML:
        // borderPane.setTop(groupsMenuScrollPane);

        // ...
    }

    public void addGroup(...) {
        // not sure exactly what you want to add, but for example,
        // to add a new image view you would do:
        ImageView imageView = new ImageView(...);
        groupContainer.getChildren().add(imageView);
    }
}

加载FXML时,保留对控制器的引用:

FXMLLoader loader = new FXMLLoader(getClass().getResource(...));
Parent root = loader.load();
HomepageController controller = loader.getController();

然后你可以用

controller.addGroup(...);

如另一个答案所述,列表视图可能是更好的方法。

您可能还应该考虑一种MVC方法(例如,请参阅将MVC与JavaFx一起应用),其中模型使用了一个可观察列表

 类似资料:
  • 我是JavaFX新手。我想与我的场景互动 例如:当我单击一个按钮时,我添加了一个新按钮,Textfield。。在里面。然而,我搜索了一下,却没有找到满意的答案! 我的fxml文件: 我的控制器: }

  • 我对JavaFX相对较新,我很困惑为什么我下面的代码没有产生预期的结果,即添加到网格中的标签。 我想做的是运行一个测试,将JavaFX标签添加到我的FXML GridPane,因为我想在不久的将来构建一个方法,允许用户选择一个文件,然后在用户选择文件时生成一个标签并将该标签添加到GridPane。 提前感谢, 代码: FXML代码是一个标准文件,其中定义了一个网格窗格,上面列出了fx:id。

  • 问题内容: 有人有使用过保险丝图形工具包的经验吗?是否可以更改已经显示的图形,即。添加/删除节点和/或边缘,并正确调整显示? 例如,prefuse附带一个示例,该示例形象化了一个朋友网络: http://prefuse.org/doc/manual/introduction/example/Example.java 我想做的事情与此类似: 但这似乎不起作用。有什么提示吗? 问题答案: 正如我在另一

  • 有什么工作可以做吗?可能是一种远程通知每个节点将新节点添加到集群的方法吗?

  • 我正在做一个需要VBoxes的“列表”表示的项目。我的应用程序分层布局是gridpane->VBox(在其中一个单元格中)->VBox(在彼此之上显示不同的数据集)->data。我有两个场景。 我的场景1控制器(控制器)如下所示: 这样设计是因为dataBox包含比标签更多的元素,但在本文中,这似乎与我无关。 我的场景2控制器(addDataController)如下所示: 我没有发布主类,因为加

  • 我试图开发一段代码来将数据从Excel文件导入/导出到Java中。我已经完成了对已定义模板的导入和导出(例如:类Employee,我知道Excel工作表在column1中有“ID”,在column2中有“Name”,等等)。我遇到的麻烦是添加列和行,以便使TableView具有与导入的Excel文件相同的信息,而不管行/列的数量如何。 当我从Excel文件导入数据时,我会将其发送到“ArrayLi