ここでリアクティブプログラミングを初めて使用します。
ReactFX を使用して JavaFX に「怠惰な」リアルタイム検索テキスト領域を実装しようとしています。ここで遅延とは、ユーザーが入力を 1 秒間停止すると検索を実行することを意味します。そのためのコードは非常に単純でした:
EventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1));
次に、そのイベント ストリームをサブスクライブすると、出来上がりです。
しかし、ユーザーが Enter キーを押すとすぐに検索を実行することも必要です。「反応的」な方法でそれを行う方法がわかりません。Enter キー イベントで検索を実行するだけで、検索が 2 回 (キー イベントに対して 1 つとテキスト変更に対して 1 つ) 発生するため、これが私の現在の解決策です。
BooleanProperty hasSearched = new SimpleBooleanProperty(false);
EventStream<KeyEvent> enterKeyPressedEvents = EventStreams.eventsOf(textArea, KeyEvent.KEY_PRESSED)
.filter(k -> k.getCode() == KeyCode.ENTER);
AwaitingEventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1));
subs = Subscription.multi(
//Text changed
textEvents.subscribe(e -> {
if (hasSearched.get()) {
hasSearched.set(false);
System.out.println("ignored text event");
} else {
performSearch(textArea.getText());
}
}),
//Enter key pressed
enterKeyPressedEvents.subscribe(e -> {
e.consume();
if (e.isShiftDown()) {
textArea.insertText(textArea.getCaretPosition(), "\n");
} else {
hasSearched.set(true);
System.out.println("enter pressed");
performSearch(textArea.getText());
if (!textEvents.isPending()) {
hasSearched.set(false);
}
}
})
);
保留中のすべてのイベントを「ドロップ」すると考えて使用してみましSuspendableEventStream.suspend()
たが、期待どおりに機能せず、保留中のイベントがまだ発行されています。
EventStream<KeyEvent> enterKeyPressedEvents = EventStreams.eventsOf(textArea, KeyEvent.KEY_PRESSED)
.filter(k -> k.getCode() == KeyCode.ENTER);
SuspendableEventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1)).suppressible();
subs = Subscription.multi(
//Text changed
textEvents.subscribe(e -> {
performSearch(textArea.getText());
}),
//Enter key pressed
enterKeyPressedEvents.subscribe(e -> {
e.consume();
if (e.isShiftDown()) {
textArea.insertText(textArea.getCaretPosition(), "\n");
} else {
Guard guard = textEvents.suspend();
System.out.println("enter pressed");
performSearch(textArea.getText());
guard.close();
}
})
);
より良い (より反応性の高い) ソリューションをどのように考えることができますか?