当前位置: 首页 > 知识库问答 >
问题:

绑定到GraphicProperty的JavaFX ImageView未在多个视图上显示

习华灿
2023-03-14

这个问题基于我之前提出的一个问题:JavaFX Sync将重复视图复制到同一个控制器(FXML)

但与另一个问题有关。我正在尝试创建一个播放/暂停按钮,每当按钮被单击到适当的位置时,该按钮就会交换图形

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...
}

按钮PanelController。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属性时,图像仅显示在第二阶段的按钮上。我的第一个阶段的按钮正在调整大小以适应图像,就像它应该的那样。当我放置断点并查看第一个按钮的“图形”属性时,我可以看到其“可观察”属性设置为我的ObjectProperty引用,但是图像本身没有显示在按钮上。第二阶段的按钮按预期工作,但第一阶段的按钮不工作。

我已经能够使用相同的架构成功绑定RadioButton的SelectedProperty,所以我不确定为什么Button的图形属性有问题。

共有1个答案

郎翔
2023-03-14

这里的概念问题是您正在使用模型来存储UI组件(例如ImageView)。模型应该存储应用程序的状态,而不是应用程序的视图。

它实际上不起作用的技术原因是一个节点只能出现在一个场景中,并且在任何场景图中最多只能出现一次。由于您在两个控制器视图对之间共享模型,因此您试图在每个视图中显示相同的ImageView实例,这是不允许的。(例如,由于您只有一个ImageView实例,您希望通过方法调用返回什么,例如playImage.get(). getScene(),或playImage.get(). getLayoutX()?)

您的模型应该只存储状态(即数据):

public class ButtonModel {
    private final BooleanProperty paused = new SimpleBooleanProperty();

    public final BooleanProperty pausedProperty() {
        return paused ;
    }

    public final boolean isPaused() {
        return pausedProperty().get();
    }

    public final void setPaused(boolean paused) {
        pausedProperty().set(paused);
    }

    public void togglePaused() {
        setPaused(! isPaused());
    }

    //... Other Getters and Setters...
}

您的控制器应该关注根据模型中的数据更新自己的视图(以及根据用户输入更新模型):

public class ButtonPanelController implements Initializable {

    // We can use a single instance of each image (which is not a node)
    // and share it between 
    // multiple image views, so we can make the images static 
    // to conserve memory. Note that fairly spectacularly bad things
    // will happen if there is an exception thrown loading these images...

    private static Image playImage = 
        new Image(ButtonPanelController.class.getResource("play.png").toExternalForm());
    private static Image pauseImage = 
        new Image(ButtonPanelController.class.getResource("pause.png").toExternalForm());

    // But each controller *must* have its own imageview to display in
    // the button in its view:

    private ImageView buttonGraphic ;

    @FXML
    Button myButton

    ButtonModel model

    public ButtonPanelController(ButtonModel model) {
        this.model = model;
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        buttonGraphic = new ImageView();
        myButton.setGraphic(buttonGraphic);
        model.setPaused(true);
        buttonGraphic.imageProperty().bind(Bindings
            .when(model.pausedProperty())
            .then(playImage)
            .otherwise(pauseImage));
    }

    public void buttonClickedAction(ActionEvent e) {
        model.togglePaused();
    }
}

请注意,您可以改为在FXML中定义ImageView并将其注入控制器:

<Button fx:id="myButton" onAction="#handleButtonAction">
    <graphic>
        <ImageView fx:id="buttonGraphic"/>
    </graphic>
</Button>

然后当然要去掉初始化方法的前两行,并用FXML注释按钮图形字段。(主要思想基本相同。)

 类似资料:
  • 我正在使用 Gradle 作为构建工具,在部署过程中,我遇到了一些我在下面提到的问题。 Gradle构建任务没有问题,但当我在tomcat8上部署它时,它显示如下错误。 build.gradle依赖文件如下: 错误消息:

  • 我一直在关注YT视频制作测验应用程序,但最终我在绑定时遇到了这个错误: “kotlin android extensions”Gradle插件已被弃用 请使用本迁移指南(https://goo.gle/kotlin-android-extensions-deprecation)开始使用视图绑定的步骤(https://developer.android.com/topic/libraries/vie

  • 本文向大家介绍backbone.js 绑定到现有HTML的视图,包括了backbone.js 绑定到现有HTML的视图的使用技巧和注意事项,需要的朋友参考一下 示例 假设此HTML在页面中: 一个视图可以绑定到它: 浏览器中的HTML现在将显示:            

  • 在从删除kotlin_extensions切换到视图绑定之后,我在onBindViewHolder方法中收到了一个“Unresolded reference:MyViewholder”,当我将“MyViewholder”替换为“holder”时,它会给我一个“Unresolded reference:bind”。我怎么解决这个问题。 MyAdapter 我试着阅读Android Studio的官方

  • 我有6个输入框,每个输入框有4位数字。输入4位数字后,光标将自动转到下一个输入框。所有这些都是强制性的。 现在,可以在“onChange”事件中将自动聚焦设置为下一个文本框。但如何将这6个输入框的值绑定到表单上的一个字段。我有办法吗?