gpt4 book ai didi

java - ReactFX - "lazy"实时搜索文本区域

转载 作者:行者123 更新时间:2023-11-30 06:08:42 28 4
gpt4 key购买 nike

这里是响应式(Reactive)编程的新手。

我正在尝试使用 ReactFX 在 JavaFX 中实现“惰性”实时搜索文本区域。这里所说的“懒惰”是指一旦用户停止输入一秒钟,它就会执行搜索。代码非常简单:

EventStream<Change<String>> textEvents = EventStreams.changesOf(textArea.textProperty())
.successionEnds(Duration.ofSeconds(1));

然后订阅该事件流即可。

但我也希望它在用户按 Enter 时立即执行搜索。我不确定如何以“响应式(Reactive)”方式做到这一点。只需在 Enter 键事件上执行搜索就会导致搜索触发两次(一次用于关键事件,一次用于文本更改),所以这是我当前的解决方案:

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();
}
})
);

我怎样才能想到更好(更具 react 性?)的解决方案?

最佳答案

这是一个解决方案。该解决方案的关键部分是观察 flatMap 内部的文本变化,这具有“重置”文本变化流的效果。

import java.time.Duration;
import java.util.function.Function;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

import org.reactfx.EventStream;
import org.reactfx.EventStreams;

public class AutoSearch extends Application {

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

@Override
public void start(Stage stage) throws Exception {
TextArea area = new TextArea();

EventStream<KeyEvent> enterPresses = EventStreams.eventsOf(area, KeyEvent.KEY_PRESSED)
.filter(k -> k.getCode() == KeyCode.ENTER)
.hook(KeyEvent::consume);

EventStream<?> searchImpulse = enterPresses.withDefaultEvent(null) // emit an event even before Enter is pressed
.flatMap(x -> {
EventStream<?> edits = EventStreams.changesOf(area.textProperty())
.successionEnds(Duration.ofSeconds(1));
return ((x == null) ? edits : edits.withDefaultEvent(null))
.map(Function.identity()); // just to get the proper type of the result
});

searchImpulse.subscribe(x -> System.out.println("Search now!"));

stage.setScene(new Scene(area));
stage.show();
}

}

关于java - ReactFX - "lazy"实时搜索文本区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39403009/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com