【问题标题】:Adding a list of specific node on a custom JavaFX FXML control在自定义 JavaFX FXML 控件上添加特定节点列表
【发布时间】:2014-11-18 16:34:56
【问题描述】:

我正在尝试在 JavaFX 中创建一个工具栏,以使用 FXML 添加按钮,如下所示:

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

<?import java.lang.*?>
<?import java.net.*?


<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.supridatta.javafx.*?>

<BorderPane xmlns:fx="http://javafx.com/fxml/1" prefHeight="200" prefWidth="320" fx:controller="com.supridatta.javafx.MainController">
    <stylesheets>
        <URL value="@main.css"/>
    </stylesheets>
    <top>
        <com.supridatta.javafx.ButtonBar fx:id="buttonBar">
            <buttons>
                <ButtonBarButton path="/com/supridatta/javafx/icons/plus.png"/>
                <ButtonBarButton path="/com/supridatta/javafx/icons/minus.png"/>
                <ButtonBarButton path="/com/supridatta/javafx/icons/last.png"/>
            </buttons>
        </com.supridatta.javafx.ButtonBar>
    </top>
    <bottom>
        <Button text="Exibir todos" onAction="#showAllButtons"/>
    </bottom>
</BorderPane>

下面是对应的java类:

package com.supridatta.javafx;

import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;

public class ButtonBar extends StackPane {

    private final HBox contentPane = new HBox();
    private final ObservableList<ButtonBarButton> buttons = FXCollections.observableArrayList();

    public ButtonBar() {
        initButtonBar();
    }

    private void initButtonBar() {
        getChildren().add(contentPane);
        setAlignment(Pos.CENTER);
        buttons.addListener(new ListChangeListener<Node>() {

            @Override
            public void onChanged(ListChangeListener.Change<? extends Node> c) {
                while (c.next()) {
                    if (c.wasAdded()) {
                        for (Node node : c.getAddedSubList()) {
                            contentPane.getChildren().add(node);
                        }
                    }
                    if (c.wasRemoved()) {
                        for (Node node : c.getAddedSubList()) {
                            contentPane.getChildren().remove(node);
                        }
                    }
                }
            }
        });
    }

    public void setButtons(ObservableList<ButtonBarButton> contents) {
        this.buttons.setAll(contents);
    }

    public ObservableList<ButtonBarButton> getButtons() {
        return buttons;
    }

    public void addButton(ButtonBarButton button) {
        buttons.add(button);
    }

    public void removeButton(ButtonBarButton button) {
        buttons.remove(button);
    }

}

当我运行项目时,我遇到了这个异常:

java.lang.IllegalArgumentException: Unable to coerce ButtonBarButton@2fd0ac8f[styleClass=button ButtonBarButton]'' to

interface javafx.collections.ObservableList.

提前致谢。

【问题讨论】:

    标签: java javafx custom-controls fxml


    【解决方案1】:

    由于您定义了setButtons 方法,FXMLLoader 将尝试将&lt;buttons&gt;...&lt;/buttons&gt; 中的元素定义的值传递给该方法。 (参见Introduction to FXML,并特别注意“只读列表属性是一个Bean 属性,其getter 返回java.util.List 的实例并且没有相应的setter 方法。”——我的重点。)

    如果你有一个getButtons() 方法返回一个列表,而没有setButtons 方法,那么FXMLLoader 会做你想做的事情,并将每个元素对应的值传递给调用的add 方法调用getButtons() 的结果。 IE。是的

    getButtons().add(new ButtonBarButton(...));
    getButtons().add(new ButtonBarButton(...));
    ...
    

    你要么希望它这样做,要么你希望它这样做

       setButtons(FXCollections.observableArrayList(new ButtonBarButton(...), new ButtonBarButton(...), ...)); 
    

    所以你有两个修复:要么从 ButtonBar 中删除 setButtons(...) 方法,要么安排传入 ObservableList

            <buttons>
                <FXCollections fx:factory="observableArrayList">
                    <ButtonBarButton path="/com/supridatta/javafx/icons/plus.png"/>
                    <ButtonBarButton path="/com/supridatta/javafx/icons/minus.png"/>
                    <ButtonBarButton path="/com/supridatta/javafx/icons/last.png"/>
                </FXCollections>
            </buttons>
    

    【讨论】:

    • 省略设置器给了我com.sun.javafx.fxml.PropertyNotFoundException: Property "cards" does not exist or is read-only.,使用FXCollections 工作但有点冗长。
    • 我猜自从这篇文章以来事情已经发生了变化,因为我还必须添加一个cardsProperty
    • 没有任何改变。如果你省略了 setter 和 &lt;FXCollections&gt; 元素,它应该可以工作,只要有一个 get 方法返回一个列表。如果没有,你还有其他问题。
    • @timdiels,删除设置器时出现错误“无效属性”。你是怎么解决的?
    • @JoãoPaulo 我不记得了,但事实证明我在 FXML 中没有 cardsProperty,但我在 this class 中有一个。也许秘密就在那个班级。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2016-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多