这个问题 Build 在我之前提出的一个问题上:JavaFX Sync Duplicate Views to the Same Controller (FXML & MVC)
但涉及一个单独的问题 . 我正在尝试创建一个播放/暂停按钮,只要按下按钮到相应的>播放和||,它就会交换图形 . 暂停图像
ButtonModel.java
public class ButtonModel {
private final ObjectProperty<ImageView> playImage = new SimpleObjectProperty<ImageView>();
private boolean paused;
public final ObjectProperty<ImageView> playImageProperty() {
return this.playImage;
}
//... Other Getters and Setters...
}
ButtonPanelController.java
public class ButtonPanelController implements Initializable {
@FXML
Button myButton
ButtonModel model
public ButtonPanelController(ButtonModel model) {
this.model = model;
}
@Override
public void initialize(URL location, ResourceBundle resources) {
model.setPaused(true);
myButton.graphicProperty().bind(model.playImageProperty());
}
public void buttonClickedAction(ActionEvent e) {
Image image = null;
if(model.isPaused()) {
image = new Image(this.getClass().getResourceAsStream("play.png"));
} else {
image = new Image(this.getClass().getResourceAsStream("pause.png"));
}
model.setPlayImage(new ImageView(image));
model.togglePaused();
}
}
我使用相同的.fxml创建两个场景,并将我的模型的单个实例传递给两个控制器以控制状态 .
我遇到的问题是,当我更改ImageView属性时,图像仅出现在我的第二阶段的按钮上 . 我的第一个舞台上的按钮正在调整大小以适应图像的样子,当我放置断点并查看第一个按钮的“图形”属性时,我可以看到它的'observable'属性设置为我的ObjectProperty参考,但是图像本身不会显示在按钮上 . 第二阶段的按钮按预期工作,但第一阶段的按钮不是 .
我已经能够使用相同的架构成功绑定RadioButton的SelectedProperty,所以我不确定为什么Button的graphicProperty有问题 .
1 回答
这里的概念问题是您使用模型来存储UI组件(例如
ImageView
) . 模型应该存储应用程序的状态,而不是应用程序的视图 .它实际上不起作用的技术原因是节点只能出现在一个场景中,而在任何场景图中最多只出现一次 . 由于您在两个控制器视图对之间共享模型,因此您尝试在每个视图中显示相同的
ImageView
实例,这是不允许的 . (例如,由于您只有一个ImageView
实例,您期望通过playImage.get().getScene()
或playImage.get().getLayoutX()
等方法调用返回什么?)您的模型应该只存储状态(即数据):
并且您的控制器应该关注基于模型中的数据更新自己的视图(以及响应用户输入更新模型):
请注意,您可以在FXML中定义
ImageView
并将其注入控制器:然后当然摆脱了
initialize
方法的前两行,并使用@FXML
注释buttonGraphic
字段 . (主要思想基本相同 . )