编程语言
首页 > 编程语言> > 在自定义JavaFX FXML控件上添加特定节点的列表

在自定义JavaFX FXML控件上添加特定节点的列表

作者:互联网

我试图在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.

提前致谢.

解决方法:

由于定义了setButtons方法,因此FXMLLoader将尝试传递由< buttons> …< / buttons>中的元素定义的值.那个方法. (请参阅Introduction to FXML,并特别注意“只读列表属性是Bean属性,其getter返回java.util.List的实例,并且没有相应的setter方法.”-我的重点.)

如果您有一个getButtons()方法返回一个列表,而没有setButtons方法,则FXMLLoader将执行您想要的操作,并将与每个元素相对应的值传递给在调用getButtons()结果时调用的add方法.即它确实

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>

标签:javafx,fxml,custom-controls,java
来源: https://codeday.me/bug/20191028/1956243.html