Feat: 为 GameList 添加搜索无结果提示 (#6566)

This commit is contained in:
快乐凤爪王 2026-08-01 21:30:26 +08:00 committed by GitHub
parent 5fc1536d6a
commit 7aeb1642b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -22,14 +22,17 @@ import com.jfoenix.controls.JFXListView;
import com.jfoenix.controls.JFXTextField;
import javafx.animation.PauseTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
@ -56,6 +59,7 @@ import org.jackhuang.hmcl.ui.directory.GameDirectoryListItem;
import org.jackhuang.hmcl.ui.directory.GameDirectoryPage;
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
import org.jackhuang.hmcl.util.FXThread;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
@ -195,6 +199,9 @@ public class GameListPage extends DecoratorAnimatedPage implements DecoratorPage
private final HBox searchBar;
private final HBox toolbarNormal;
/// Whether the search mechanism is currently active.
private final BooleanProperty isSearching = new SimpleBooleanProperty(false);
private final JFXTextField searchField;
public GameListSkin(GameList skinnable) {
@ -222,13 +229,19 @@ public class GameListPage extends DecoratorAnimatedPage implements DecoratorPage
PauseTransition pause = new PauseTransition(Duration.millis(100));
pause.setOnFinished(e -> skinnable.filteredList.setPredicate(skinnable.createPredicate(searchField.getText())));
searchField.textProperty().addListener((observable, oldValue, newValue) -> {
pause.setRate(1);
pause.playFromStart();
if (isSearching.get() || !StringUtils.isBlank(newValue)) {
pause.setRate(1);
pause.playFromStart();
}
});
JFXButton closeSearchBar = createToolbarButton2(null, SVG.CLOSE, () -> {
changeToolbar(toolbarNormal);
searchField.clear();
pause.stop();
skinnable.filteredList.setPredicate(null);
isSearching.set(false);
});
onEscPressed(searchField, closeSearchBar::fire);
@ -255,6 +268,15 @@ public class GameListPage extends DecoratorAnimatedPage implements DecoratorPage
ignoreEvent(listView, KeyEvent.KEY_PRESSED, e -> e.getCode() == KeyCode.ESCAPE);
StackPane placeholderContainer = new StackPane();
placeholderContainer.getStyleClass().add("notice-pane");
Label placeholderLabel = new Label();
placeholderLabel.textProperty().bind(
Bindings.when(isSearching).then(i18n("search.no_results_found")).otherwise("")
);
placeholderContainer.getChildren().add(placeholderLabel);
listView.setPlaceholder(placeholderContainer);
center.setContent(listView);
root.getContent().add(center);
}
@ -269,6 +291,8 @@ public class GameListPage extends DecoratorAnimatedPage implements DecoratorPage
toolbarPane.setContent(newToolbar, ContainerAnimations.FADE);
if (newToolbar == searchBar) {
runInFX(searchField::requestFocus);
isSearching.set(true);
}
}
}