【问题标题】:I would like to dynamicaly create nodes in a javaFX from a template我想从模板动态创建 javaFX 中的节点
【发布时间】:2022-01-11 19:06:34
【问题描述】:

我无法弄清楚如何在 JavaFX 中动态创建节点,我正在尝试为消息传递程序创建一个接口,并且我希望每条消息都包含在它自己的节点中。我不知道会发送多少条消息,所以我需要根据需要创建新节点。

这是我目前想要做的,所以我可以添加多个 MessageNode 对象并让它们显示

package stackkoverflow.stackoverflow;

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class MessageControler {
    @FXML
    private Label sender;
    @FXML
    private Label message;

    private MessageNode messagenode;

    public MessageControler(MessageNode messagenode){
        this.messagenode = messagenode;
    }

    @FXML
    private void initialize(){
        sender.textProperty().bind(messagenode.senderProperty());
        message.textProperty().bind(messagenode.messageProperty());
    }

}
package stackkoverflow.stackoverflow;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class MessageNode {

    private StringProperty sender = new SimpleStringProperty();
    private StringProperty message = new SimpleStringProperty();

    public MessageNode(String sender, String message){
        this.sender.set(sender);
        this.message.set(message);
    }

    public String getSender(){
        return sender.get();
    }
    public String getMessage(){
        return message.get();
    }
    public void setSender(String sender) {
        this.sender.set(sender);
    }
    public void setMessage(String message) {
        this.message.set(message);
    }
    public StringProperty senderProperty(){
        return sender;
    }
    public StringProperty messageProperty(){
        return message;
    }



}
package stackkoverflow.stackoverflow;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class test extends Application {


    @Override
    public void start(Stage primaryStage) {
        MessageNode messageNodeTest = new MessageNode("user","hello world");
        MessageNode messageNodeTest1 = new MessageNode("user","hello world");
        MessageNode messageNodeTest2 = new MessageNode("user","hello world");
        MessageNode messageNodeTest3 = new MessageNode("user","hello world");

        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Display.fxml"));
            MessageControler controller = new MessageControler(messageNodeTest);

            loader.setController(controller);

            primaryStage.setScene(new Scene(loader.load()));
            primaryStage.show();

        }catch (IOException ie){
            ie.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

}

【问题讨论】:

  • 这个问题非常模糊和广泛。你能具体解释一下是什么问题吗?以minimal reproducible example 的形式包含代码,以更好地描述问题。
  • 目前还不清楚问题是什么。你已经准备好了所有的部分。每次收到新消息时,像之前一样再次加载 FXML,并将生成的节点添加到 UI 的某个位置(例如,在 VBox 或类似的地方)。
  • 当然,您也可以将ListView<MessageNode> 与适当的单元工厂一起使用,然后将您的消息添加到其items 列表中。
  • 我想我想做的是你用 LIstView 描述的内容,我该怎么做?
  • 使用ListCells 加载FXML,然后在关联控制器上设置MessageNode

标签: java javafx fxml


【解决方案1】:

您可以加载 FXML 并在 ListCell 中显示每个实例,将 MessageNodes 添加到 ListView<MessageNode>

首先,更改您的MessageController 类,以便可以更改MessageNode(注意:我将重命名该类Message,因为它是数据而不是场景图节点)。这很重要,因为您只想为每个单元格加载一次 FXML,而不是为每个项目加载一次:

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class MessageController {
    @FXML
    private Label sender;
    @FXML
    private Label message;

    private MessageNode messageNode ;

    public void setMessageNode(MessageNode messageNode){
        this.messageNode = messageNode ;
        sender.textProperty().unbind();
        message.textProperty().unbind();
        if (messageNode == null) {
            sender.setText("");
            message.setText("");
        } else {
            sender.textProperty().bind(messageNode.senderProperty());
            message.textProperty().bind(messageNode.messageProperty());
        }
    }

}

现在你可以这样做了:

// injected by FXML or just created in code, as needed:
ListView<MessageNode> listView ;

// ...

listView.setCellFactory(lv -> new ListCell<>() {

    private Node graphic ;
    private MessageController controller ;

    {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Display.fxml"));
            graphic = loader.load();
            controller = loader.getController();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    @Override
    protected void updateItem(MessageNode message, boolean empty) {
        super.updateItem(message, empty);
        controller.setMessageNode(message);
        if (empty || message == null) {
            setGraphic(null);
        } else {
            setGraphic(graphic);
        }
    }
});

当然可以

listView.getItems().add(new MessageNode(...));

您需要的任何时间。

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    相关资源
    最近更新 更多