Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使JavaFX属性侦听器在oldVaule和newValue相同的情况下触发事件? 让我们考虑一个示例代码: SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(0); simpleIntegerProperty.addListener((observable, oldValue, newValue) -> { // execution code when the event is fired. });_Java_Javafx - Fatal编程技术网

如何使JavaFX属性侦听器在oldVaule和newValue相同的情况下触发事件? 让我们考虑一个示例代码: SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(0); simpleIntegerProperty.addListener((observable, oldValue, newValue) -> { // execution code when the event is fired. });

如何使JavaFX属性侦听器在oldVaule和newValue相同的情况下触发事件? 让我们考虑一个示例代码: SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(0); simpleIntegerProperty.addListener((observable, oldValue, newValue) -> { // execution code when the event is fired. });,java,javafx,Java,Javafx,使用setValue()方法设置新值时,如果oldValue和newValue相同,则不会触发事件。只有当他们不同的时候 一个例子: 我有一个列表视图与包含一些“元素”的可观察列表绑定在一起 我可以在应用程序的不同位置添加更多元素 有一个按钮“开始”启动一个程序-它 遍历列表并对每个元素执行一些操作 过程是另一类。它对元素执行一些操作,还包含simpleintegerperty-currentlyChosenElementIndex,以指示当前所选元素的索引 当当前元素正在进行时,我希望Li

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

一个例子:

  • 我有一个
    列表视图
    与包含一些“元素”的
    可观察列表绑定在一起
  • 我可以在应用程序的不同位置添加更多元素
  • 有一个按钮“开始”启动一个程序-它 遍历列表并对每个元素执行一些操作
  • 过程是另一类。它对元素执行一些操作,还包含
    simpleintegerperty
    -
    currentlyChosenElementIndex
    ,以指示当前所选元素的索引
当当前元素正在进行时,我希望
ListView
显示这一点。现在,在该过程中,GUI被阻止,并且当前元素在执行过程中在
列表视图上被选中。程序结束后,应用程序将CurrentLyHosenElementIndex重置为零,这是一个索引,我有问题。当过程开始时,第一个元素不会被选择,因为应用程序
setValue()
与以前的相同


有什么方法可以改变这一点吗?

您不能简单地使用
SimpleIntegerProperty
类来实现这一点。但您可以扩展类并添加所需的功能。创建这样一个类

public class NotifySetIntegerProperty extends SimpleIntegerProperty {
    private OnSetValueListener valueListener;

    public NotifySetIntegerProperty(int initialValue) {
        super(initialValue);
    }

    @Override
    public void set(int newValue) {
        super.set(newValue);
        if(valueListener!= null) {
            valueListener.onValueSet(newValue);
        }
    }

    public void setValueListener(OnSetValueListener valueListener) {
        this.valueListener = valueListener;
    }

    public interface OnSetValueListener {
        void onValueSet(int value);
    }
}
然后您可以使用它,并在调用
setValue
set
方法时收到通知

NotifySetIntegerProperty property = new NotifySetIntegerProperty(0);
property.setValueListener(new NotifySetIntegerProperty.OnSetValueListener() {
    @Override
    public void onValueSet(int value) {
        System.out.println(value);
    }
});
property.setValue(1);
property.setValue(0);
将输出

1
0

如果您的
过程
currentlyChosenElementIndex
表示当前正在处理的元素的索引,那么当当前没有处理任何元素时,将其等于
0
基本上会使应用程序处于不一致的状态。对于表示索引的内容,通常的约定是使用
-1
表示“无值”。因此,我认为将
currentlyChosenElementIndex
初始化为
-1
,并在过程完成后将其重置为
-1
更有意义。(当未选择任何内容时,这也将与选择模型的选定索引一致。)

这意味着您在使用该值时必须小心,以避免任何
ArrayIndexOutOfBoundsException
s-即,您必须检查特殊值并单独处理

这里有一个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);
    }
}
import java.util.List;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.ReadOnlyIntegerProperty;
导入javafx.beans.property.ReadOnlyIntegraterRapper;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.ListView;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.BorderPane;
导入javafx.scene.layout.HBox;
导入javafx.stage.stage;
公共类ProcessListElements扩展了应用程序{
私有整数计数=0;
@凌驾
公共无效开始(阶段primaryStage){
ListView ListView=新建ListView();
对于(inti=0;i<10;i++)addElement(listView.getItems());
程序程序=新程序();
按钮启动流程按钮=新按钮(“启动流程”);
按钮addItemButton=新按钮(“添加项”);
按钮deleteItemButton=新按钮(“删除项目”);
TextArea log=新建TextArea();
启动进程按钮。设置操作(e->{
log.clear();
requestFocus();
新线程(()->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().SelectEditeProperty().isNull());
HBox controls=新HBox(5,StartProcess按钮、addItemButton、deleteItemButton);
控件。设置对齐(位置中心);
控件。设置填充(新插图(5));
BorderPane root=新的BorderPane(listView,null,log,controls,null);
procedure.currentlychosenelementindex exproperty().addListener((obs、旧索引、新索引)->{
Platform.runLater(()->
listView.getSelectionModel().clearAndSelect(newIndex.intValue());
});
procedure.currentlychosenelementindex exproperty().addListener((obs、旧索引、新索引)->{
Platform.runLater(()->{
controls.setDisable(newIndex.intValue()!=Procedure.NO_元素);
});
});
procedure.currentlychosenelementindex exproperty().addListener((obs、旧索引、新索引)->{
if(oldIndex.intValue()!=过程。无\u元素){
log.appendText(“元素处理”+oldIndex.intValue()+“完成”\n”);
}
if(newIndex.intValue()!=Procedure.NO_元素){
log.appendText(“处理元素”+newIndex.intValue()+“已启动”\n”);
}
});
场景=新场景(root,600600);
初级阶段。场景(场景);
primaryStage.show();
}
专用无效补遗(列表){
计数++;
列表。添加(“项目”+计数);
}
公共静态类程序{
私有静态final int NO_元素=-1;
private final ReadOnlyIntegraterRapper CurrentlyHosenElementIndex=新的ReadOnlyIntegraterRapper(无元素);
公共作废流程(列表项){
if(Platform.isFxApplicationThread()){
抛出新的IllegalStateException(“此方法阻塞并且不能执行到
class DelicateSimpleDoubleProperty extends SimpleDoubleProperty{
            @Override
            public void set( double newValue ) {
                if (get() == newValue){
                    super.set(newValue + 0.0000000000001);
                }else {
                    super.set(newValue);
                }
            } 
}