即使 oldVaule 和 newValue 相同,如何使 JavaFX 属性侦听器触发事件?

普热米斯瓦夫·塔蒙

让我们考虑一个示例代码:

SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(0);
simpleIntegerProperty.addListener((observable, oldValue, newValue) -> {
  // execution code when the event is fired.
});

当我使用setValue()方法设置新值时,如果 oldValue 和 newValue 相同,则不会触发该事件。只有当它们不同时。

一个例子:

  • 我有一个包含一些“元素”ListView<Element>绑定ObservableList<Element>
  • 我可以在应用程序的不同位置添加更多元素。
  • 有一个按钮“开始”,它启动一个过程——它遍历列表并对每个元素执行一些操作。
  • AProcedure是一个不同的类。它对元素执行一些操作,并且还包含SimpleIntegerPorperty-currentlyChosenElementIndex以指示当前所选元素的索引。

在处理当前元素时,我希望ListView显示这一点。现在,在此过程中,GUI 被阻止ListView,并且在进行时在 上选择当前元素程序结束后,应用程序重置currentlyChosenElementIndex为零,这是我遇到问题的索引。当程序开始时,第一个元素没有被选中,因为应用程序setValue()与之前的元素相同。

有什么办法可以改变吗?

詹姆斯_D

如果您的ProcedurecurrentlyChosenElementIndex表示当前正在被处理,然后将具有它等于元素的索引0没有元件当前正在处理的基本叶处于不一致的状态应用程序。表示索引的东西的通常约定是-1用来表示“无值”。所以我认为初始化currentlyChosenElementIndex-1,并-1在程序完成时将其重置为更有意义(这也会与选择模型的选择索引一致,当什么都没有选择时。)

这确实意味着您在使用该值时必须小心,以避免出现任何ArrayIndexOutOfBoundsExceptions - 即您必须检查特殊值并单独处理它。

这是一个 SSCCE:

import java.util.List;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.ReadOnlyIntegerWrapper;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ProcessListElements extends Application {

    private int count = 0 ;

    @Override
    public void start(Stage primaryStage) {
        ListView<String> listView = new ListView<>();
        for (int i = 0 ; i < 10 ; i++) addElement(listView.getItems());

        Procedure procedure = new Procedure();

        Button startProcessButton = new Button("Start Process");
        Button addItemButton = new Button("Add item");
        Button deleteItemButton = new Button("Delete item");

        TextArea log = new TextArea();

        startProcessButton.setOnAction(e -> {
            log.clear();
            listView.requestFocus();
            new Thread(() -> procedure.process(listView.getItems())).start();
        });

        addItemButton.setOnAction(e -> addElement(listView.getItems()));
        deleteItemButton.setOnAction(e -> listView.getItems().remove(listView.getSelectionModel().getSelectedIndex()));
        deleteItemButton.disableProperty().bind(listView.getSelectionModel().selectedItemProperty().isNull());

        HBox controls = new HBox(5, startProcessButton, addItemButton, deleteItemButton);
        controls.setAlignment(Pos.CENTER);
        controls.setPadding(new Insets(5));


        BorderPane root = new BorderPane(listView, null, log, controls, null);

        procedure.currentlyChosenElementIndexProperty().addListener((obs, oldIndex, newIndex) -> {
            Platform.runLater(() -> 
                listView.getSelectionModel().clearAndSelect(newIndex.intValue()));
        });

        procedure.currentlyChosenElementIndexProperty().addListener((obs, oldIndex, newIndex) -> {
            Platform.runLater(() -> {
                controls.setDisable(newIndex.intValue() != Procedure.NO_ELEMENT);
            });
        });

        procedure.currentlyChosenElementIndexProperty().addListener((obs, oldIndex, newIndex) -> {
            if (oldIndex.intValue() != Procedure.NO_ELEMENT) {
                log.appendText("Processing of element "+oldIndex.intValue()+" complete\n");
            }
            if (newIndex.intValue() != Procedure.NO_ELEMENT) {
                log.appendText("Processing element "+newIndex.intValue()+" started\n");
            }
        });


        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void addElement(List<String> list) {
        count++ ;
        list.add("Item "+count);
    }

    public static class Procedure {

        private static final int NO_ELEMENT = - 1; 

        private final ReadOnlyIntegerWrapper currentlyChosenElementIndex = new ReadOnlyIntegerWrapper(NO_ELEMENT);

        public void process(List<?> items) {
            if (Platform.isFxApplicationThread()) {
                throw new IllegalStateException("This method blocks and must not be executed on the FX Application Thread");
            }
            try {
                for (int i = 0 ; i < items.size(); i++) {
                    currentlyChosenElementIndex.set(i);
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            currentlyChosenElementIndex.set(NO_ELEMENT);
        }

        public final ReadOnlyIntegerProperty currentlyChosenElementIndexProperty() {
            return this.currentlyChosenElementIndex.getReadOnlyProperty();
        }


        public final int getCurrentlyChosenElementIndex() {
            return this.currentlyChosenElementIndexProperty().get();
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

JavaFx:侦听器和/或绑定处理

JavaFX中的ToggleButtons和侦听器

JavaFx和套接字侦听器

如何在会话和路由器侦听器之间注册事件侦听器?

webRTC ondatachannel() 和 onopen() 事件侦听器未触发

如何设置滑块更改侦听器仅在JavaFX中释放鼠标拖动时才触发?

如何从JavaFX中的其他控件事件侦听器更改Slider值?

JavaFX:如何将侦听器设置为TabPane标头的onClick事件

JavaFX:如何将侦听器设置为TabPane标头的onClick事件

如何准确识别事件侦听器触发的元素?

JavaFX事件/侦听器/处理程序

即使在活动完成后 Firebase 值事件侦听器也会触发?

即使给定相同的属性和值,按钮大小也不同

如何在Lit-HTML中使用事件侦听器添加和删除类?

JS-如何在事件中分配和添加侦听器?

无论验证条件和表单事件侦听器如何,表单都提交

如何使用Javascript验证和PHP处理事件侦听器

如何在 puppeteer 中使用单击事件侦听器查找元素名称和值

侦听器JavaFX

具有不同触发器元素和侦听器元素的自定义事件

整理和多个事件侦听器

事件侦听器和转换 JS

如何处理Property <T>,更改侦听器和属性的初始化?

如何设置事件侦听器并使用react钩子在首次触发事件后将其删除?

Spring 3.1和Quartz中的作业侦听器和触发器侦听器

AngularJS:为什么要在`$ watch`监听器中检查newValue是否与oldValue相同?

如何添加触发将某种类型的元素添加到DOM的事件侦听器?

如何实现SQL Server事件侦听器以触发Nodejs函数?

如何在<head>中的脚本标记中触发事件侦听器