[Bugfix] 修复列表中涟漪状态不更新的问题 (#6586)

Fixes #6549
This commit is contained in:
ToobLac 2026-08-13 20:49:17 +08:00 committed by GitHub
parent 5c364f624a
commit a3c5e8e412
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 48 additions and 11 deletions

View file

@ -70,7 +70,7 @@ public class JFXComboBox<T> extends ComboBox<T> {
private void initialize() {
getStyleClass().add(DEFAULT_STYLE_CLASS);
this.setCellFactory(listView -> new JFXListCell<T>() {
this.setCellFactory(listView -> new JFXListCell<>() {
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
@ -80,7 +80,7 @@ public class JFXComboBox<T> extends ComboBox<T> {
// had to refactor the code out of the skin class to allow
// customization of the button cell
this.setButtonCell(new ListCell<T>() {
this.setButtonCell(new ListCell<>() {
{
// fixed clearing the combo box value is causing
// java prompt text to be shown because the button cell is not updated

View file

@ -199,6 +199,7 @@ public class JFXListCell<T> extends ListCell<T> {
*/
@Override
protected void updateItem(T item, boolean empty) {
cellRippler.releaseRippleImmediately();
super.updateItem(item, empty);
if (empty) {
setText(null);

View file

@ -278,6 +278,10 @@ public class JFXRippler extends StackPane {
rippler.releaseRipple();
}
public void releaseRippleImmediately() {
rippler.releaseRippleImmediately();
}
/**
* creates Ripple effect in the center of the control
*
@ -405,6 +409,22 @@ public class JFXRippler extends StackPane {
}
}
private void releaseRippleImmediately() {
Ripple ripple = ripplesQueue.poll();
if (ripple != null) {
getChildren().remove(ripple);
if (generating.getAndSet(false)) {
if (overlayRect != null) {
overlayRect.inAnimation.stop();
if (!forceOverlay) {
overlayRect.outAnimation.stop();
overlayRect.setOpacity(0D);
}
}
}
}
}
void cacheRippleClip(boolean cached) {
cacheRipplerClip = cached;
}

View file

@ -1394,7 +1394,7 @@ public final class FXUtils {
}
public static <T> Callback<ListView<T>, ListCell<T>> jfxListCellFactory(Function<T, Node> graphicBuilder) {
return view -> new JFXListCell<T>() {
return view -> new JFXListCell<>() {
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);

View file

@ -39,7 +39,7 @@ public final class FontComboBox extends JFXComboBox<String> {
styleProperty().bind(Bindings.concat("-fx-font-family: \"", valueProperty(), "\""));
setCellFactory(listView -> new JFXListCell<String>() {
setCellFactory(listView -> new JFXListCell<>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);

View file

@ -30,6 +30,7 @@ public abstract class MDListCell<T> extends ListCell<T> {
private final StackPane container = new StackPane();
private final StackPane root = new StackPane();
private final RipplerContainer ripplerContainer = new RipplerContainer(container);
public MDListCell(JFXListView<T> listView) {
@ -37,7 +38,6 @@ public abstract class MDListCell<T> extends ListCell<T> {
setGraphic(null);
root.getStyleClass().add("md-list-cell");
RipplerContainer ripplerContainer = new RipplerContainer(container);
root.getChildren().setAll(ripplerContainer);
Region clippedContainer = (Region) listView.lookup(".clipped-container");
@ -56,12 +56,13 @@ public abstract class MDListCell<T> extends ListCell<T> {
T oldItem = getItem();
boolean oldEmpty = isEmpty();
ripplerContainer.releaseRippleImmediately();
super.updateItem(item, empty);
if (oldItem == item && oldEmpty == empty) return;
updateControl(item, empty);
if (empty) {
if (empty || item == null) {
setGraphic(null);
} else {
setGraphic(root);

View file

@ -205,6 +205,10 @@ public class RipplerContainer extends StackPane {
ripplerFillProperty().set(ripplerFill);
}
public void releaseRippleImmediately() {
buttonRippler.releaseRippleImmediately();
}
@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return getClassCssMetaData();

View file

@ -158,6 +158,7 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab
private final TwoLineListItem twoLineListItem = new TwoLineListItem();
private final ImageView imageView = new ImageView();
private final StackPane pane = new StackPane();
private final RipplerContainer ripplerContainer;
RemoteVersionListCell(VersionsPage control) {
this.control = control;
@ -188,7 +189,7 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab
pane.getStyleClass().add("md-list-cell");
StackPane.setMargin(hbox, new Insets(10, 16, 10, 16));
pane.getChildren().setAll(new RipplerContainer(hbox));
pane.getChildren().setAll(ripplerContainer = new RipplerContainer(hbox));
FXUtils.onClicked(this, this::onAction);
}
@ -214,6 +215,7 @@ public final class VersionsPage extends Control implements WizardPage, Refreshab
public void updateItem(RemoteVersion remoteVersion, boolean empty) {
RemoteVersion oldRemoteVersion = getItem();
ripplerContainer.releaseRippleImmediately();
super.updateItem(remoteVersion, empty);
if (empty) {

View file

@ -581,6 +581,7 @@ public class DownloadListPage extends Control implements DecoratorPage, GameInst
@Override
protected void updateItem(RemoteAddon item, boolean empty) {
this.graphic.releaseRippleImmediately();
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);

View file

@ -40,7 +40,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class GameListCell extends ListCell<GameListItem> {
private final Region graphic;
private final RipplerContainer graphic;
private final ImageContainer imageView;
private final TwoLineListItem content;
@ -162,6 +162,7 @@ public final class GameListCell extends ListCell<GameListItem> {
@Override
public void updateItem(GameListItem item, boolean empty) {
this.graphic.releaseRippleImmediately();
super.updateItem(item, empty);
this.imageView.imageProperty().unbind();

View file

@ -115,6 +115,7 @@ public final class GameListPopupMenu extends StackPane {
private static final class Cell extends ListCell<GameItem> {
private final Region graphic;
private final RipplerContainer ripplerContainer;
private final ImageContainer imageView;
private final TwoLineListItem content;
@ -143,7 +144,7 @@ public final class GameListPopupMenu extends StackPane {
container.setLeft(imageView);
container.setCenter(content);
RipplerContainer ripplerContainer = new RipplerContainer(container);
this.ripplerContainer = new RipplerContainer(container);
StackPane rootPane = new StackPane();
rootPane.getStyleClass().add("advanced-list-item");
@ -164,6 +165,7 @@ public final class GameListPopupMenu extends StackPane {
@Override
protected void updateItem(GameItem item, boolean empty) {
this.ripplerContainer.releaseRippleImmediately();
super.updateItem(item, empty);
this.imageView.imageProperty().unbind();

View file

@ -598,6 +598,7 @@ public final class SchematicsPage extends ListPageBase<SchematicsPage.Item> impl
@Override
protected void updateItem(Item item, boolean empty) {
graphics.releaseRippleImmediately();
super.updateItem(item, empty);
iconImageView.setImage(null);

View file

@ -326,6 +326,7 @@ public final class WorldListPage extends ListPageBase<World> implements GameInst
World oldWorld = getItem();
boolean oldEmpty = isEmpty();
this.graphic.releaseRippleImmediately();
super.updateItem(world, empty);
if (oldWorld == world && oldEmpty == empty) return;

View file

@ -227,7 +227,7 @@ public final class JavaManagementPage extends ListPageBase<JavaRuntime> {
}
private static final class JavaItemCell extends ListCell<JavaRuntime> {
private final Node graphic;
private final RipplerContainer graphic;
private final Label label = new Label();
private final TwoLineListItem content;
@ -298,6 +298,8 @@ public final class JavaManagementPage extends ListPageBase<JavaRuntime> {
@Override
protected void updateItem(JavaRuntime item, boolean empty) {
JavaRuntime oldItem = getItem();
this.graphic.releaseRippleImmediately();
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);

View file

@ -632,7 +632,7 @@ public final class ThemePackManagementPage extends ListPageBase<ThemePackManager
private final ThemePackManagementPage page;
/// Root graphic reused by this cell.
private final Region graphic;
private final RipplerContainer graphic;
/// The text content shown for the current theme pack.
private final TwoLineListItem content = new TwoLineListItem();
@ -715,6 +715,7 @@ public final class ThemePackManagementPage extends ListPageBase<ThemePackManager
protected void updateItem(ThemePackManager.@Nullable InstalledThemePack themePack, boolean empty) {
var currentItem = getItem();
this.graphic.releaseRippleImmediately();
super.updateItem(themePack, empty);
if (Objects.equals(getItem(), currentItem)) return;