向列表单元格添加投影后悬停和选择事件被窃听

After adding a drop shadow to a list cell hovering and selection events are bugged

所以我将下面的 fx-css 添加到 list-cell.

.list-cell:selected:filled:hover {
    -fx-view-order: -1;
    -fx-effect: dropshadow(gaussian, #67676D, 12, 0.05, 0.0, 2);
}

请注意,当列表单元格为 :selected 时,其背景为灰色。

现在节点边界似乎延伸到周围单元格上的阴影的末端。这种行为是不需要的,因为带有阴影的单元格捕获的事件实际上应该由下面或上面的单元格处理。

有解决办法吗?

注意:可以将相同的 fx-css 应用于 table-view,并且不会出现这种不需要的功能。

public class ListViewTest {
    @Test
    public void testFx() throws InterruptedException {
        new JFXPanel();
        CountDownLatch latch = new CountDownLatch(1);
        Platform.runLater(() -> {
            ListView<String> lv =  new ListView<>();

            lv.setCellFactory(param -> new ListCell<>() {

                {
                    setPrefHeight(38);
                    hoverProperty().addListener((observable, oldValue, newValue) -> {
                            if (newValue) {
                                setStyle("""
                                    -fx-view-order: -1;
                                    -fx-effect: dropshadow(gaussian, #67676D, 12, 0.05, 0.0, 2);
                                """);
                            } else {
                                setStyle(null);
                            }
                        });
                }

                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    if (empty || item == null) {

                    } else {

                    }
                }
            });
            var items = FXCollections.observableArrayList("1", "2", "3");
            lv.setItems(items);
            Stage stage = new Stage();
            Scene scene = new Scene(lv);
            stage.setScene(scene);
            stage.show();
        });
        latch.await();
    }
}

关于您的备注:

Note: the same fx-css can be applied to a table-view and this unwanted functionally does not occur.

我假设您将样式应用于 table 而不是 table 单元格 .我做出这个假设有几个原因:

  • Table 个单元格,至少在默认情况下,似乎没有背景。这意味着在我的测试中投影应用于单元格的文本而不是整个单元格。
  • 只有 TableRowSkinBase 做了一些与 ListCellSkin 不同的事情,这可能与这个问题有关。

第二点提到的区别是对setPickOnBounds(false)的调用。 ListCell 不需要这样做。显然,投影增加了单元格的边界,导致它与相邻单元格重叠,并且由于拾取边界是正确的,这意味着鼠标悬停在单元格上的时间比“预期”长。

只需在您的自定义列表单元格上调用 setPickOnBounds(false) 即可解决此问题。例如:

Main.java:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.stage.Stage;

public class Main extends Application {

  @Override
  public void start(Stage primaryStage) {
    var listView = new ListView<String>();
    listView.getItems().addAll("1", "2", "3", "4", "5");

    listView.setCellFactory(
        lv ->
            new ListCell<>() {

              {
                setPrefHeight(38);
                setPickOnBounds(false); // fix for issue
              }

              @Override
              protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                if (empty || item == null) {
                  setText(null);
                } else {
                  setText(item);
                }
              }
            });

    var scene = new Scene(listView, 600, 400);
    scene.getStylesheets().add(getClass().getResource("/test.css").toString());
    primaryStage.setScene(scene);
    primaryStage.show();
  }
}

test.css:

.list-cell:selected:filled:hover {
  -fx-view-order: -1;
  -fx-effect: dropshadow(gaussian, #67676D, 12, 0.05, 0.0, 2);
}

注意:我不知道调用setPickOnBounds(false)是否会导致其他问题。