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