我正在尝试在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.
提前致谢。
答案 0 :(得分:4)
由于您定义了setButtons
方法,FXMLLoader
将尝试将<buttons>...</buttons>
内的元素定义的值传递给该方法。 (参见Introduction to FXML,特别注意“只读列表属性是一个Bean属性,其getter返回java.util.List
的实例,并且没有相应的setter方法。” - 我的重点。)
如果您有getButtons()
方法返回列表,而没有setButtons
方法,那么FXMLLoader
将执行您想要的操作,并将与每个元素对应的值传递给{调用add
的结果调用了{1}}方法。即它确实
getButtons()
你要么想要它呢,要么你想要它做
getButtons().add(new ButtonBarButton(...));
getButtons().add(new ButtonBarButton(...));
...
所以你有两个修正:要么从 setButtons(FXCollections.observableArrayList(new ButtonBarButton(...), new ButtonBarButton(...), ...));
删除setButtons(...)
方法,要么安排传递ButtonBar
:
ObservableList