有没有办法继续监听属性更改,几秒钟,然后触发事件(调用方法)?
例如,当用户在文本字段中输入数据时:
textField.textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2) {
//before calling a method to do something.. wait for a few seconds ...
}
});
方案将基于字符串值触发操作。例如,按“M”表示移动,或“MA”表示屏蔽。我想在继续采取行动之前“继续听”2秒钟。
答案 0 :(得分:4)
正如杰弗里指出的那样,你可以使用ReactFX:
EventStreams.valuesOf(textField.textProperty())
.successionEnds(Duration.ofSeconds(2))
.subscribe(s -> doSomething(s));
答案 1 :(得分:2)
有几种方法可以解决这个问题。
通常我会推荐Java Timer API,但如果通过“制作动作”暗示更新FX线程上的内容,则必须同步线程,这很麻烦。
根据您的使用情况,您可以使用转换或FX中的时间轴。
以下是转换的示例:
包裹申请;
import javafx.animation.RotateTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TransitionedInputExample extends Application {
@Override
public void start(final Stage stage) {
final ImageView spinner =
new ImageView("https://cdn1.iconfinder.com/data/icons/duesseldorf/16/process.png");
spinner.setVisible(false);
final Label title = new Label("Timed Action Commander Example", spinner);
title.setContentDisplay(ContentDisplay.BOTTOM);
title.setFont(Font.font("Helvetica", FontWeight.BOLD, FontPosture.REGULAR, 16));
final TextField textInput = new TextField();
textInput.setPromptText("Enter command");
final TextArea textOutput = new TextArea();
textOutput.setPromptText("Command results will show up here");
final VBox layout = new VBox(title, textInput, textOutput);
layout.setSpacing(24);
// setup some transition that rotates an icon for 2 seconds
final RotateTransition rotateTransition = new RotateTransition(Duration.seconds(1), spinner);
rotateTransition.setByAngle(90);
// delay rotation so that user can type without being distracted at once
rotateTransition.setDelay(Duration.seconds(1));
// restart transition on user input
textInput.textProperty().addListener((observable, oldText, newText) -> {
spinner.setVisible(true);
rotateTransition.playFromStart();
});
rotateTransition.setOnFinished((finishHim) -> {
// execute command
textOutput.setText("Executing " + textInput.getText());
spinner.setVisible(false);
});
final Scene scene = new Scene(layout);
stage.setScene(scene);
stage.show();
}
public static void main(final String[] args) {
launch(args);
}
}
对于使用时间轴的解决方案,请参阅this post。
答案 2 :(得分:1)
您可以考虑使用Inhibeans。它允许您阻止事件的处理,直到您希望触发更改事件。整个ReactFX项目也可能有用,因为您需要做的基本上是构建事件的状态机。您正在寻找像正则表达式这样的事件中的模式。
例如,假设您使用'M'表示移动,使用'MA'表示遮罩。通过状态机,您将拥有两条路径。
中号
M - &gt;甲
然后,您可以使用计时器来确定在处理事件之前等待事件堆积的时间。
结帐sample copied from the ReactFX site:
累积紧密时间序列中发出的事件为一个。
EventSource<Integer> source = new EventSource<>();
EventStream<Integer> accum = source.reduceSuccessions((a, b) -> a + b, Duration.ofMillis(200));
source.push(1);
source.push(2);
// wait 150ms
source.push(3);
// wait 150ms
source.push(4);
// wait 250ms
source.push(5);
// wait 250ms
在上面的示例中,在前一个之后的200ms内发出的事件被累积(添加)到前一个事件。 accum
会发出以下值:10,5。