From 7aeb1642b1f52f1ee8cf7647ec30b4a164910ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BF=AB=E4=B9=90=E5=87=A4=E7=88=AA=E7=8E=8B?= <165921128+KSSJW@users.noreply.github.com> Date: Sat, 1 Aug 2026 21:30:26 +0800 Subject: [PATCH] =?UTF-8?q?Feat:=20=E4=B8=BA=20GameList=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=90=9C=E7=B4=A2=E6=97=A0=E7=BB=93=E6=9E=9C=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=20(#6566)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/ui/instances/GameListPage.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/GameListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/GameListPage.java index c8e55cfdd2..55a6118b39 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/GameListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/GameListPage.java @@ -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); } } }