Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
720 views
in Technique[技术] by (71.8m points)

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

So I added the below fx-css to a list-cell.

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

Note when a list-cell is :selected its background is grey.

Now it seems the node boundaries are extended to the end of the drop shadow over the surrounding cells. This behavior is unwanted as the cell with the shadow captures events that should really be handled by the below or above cell.

enter image description here

Is there a fix for this?

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

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();
    }
}
question from:https://stackoverflow.com/questions/65929630/after-adding-a-drop-shadow-to-a-list-cell-hovering-and-selection-events-are-bugg

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Regarding your note:

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

I assume you're applying the style to the table rows and not the table cells. I'm making that assumption for a couple reasons:

  • Table cells, at least by default, don't seem to have a background. This means the drop shadow was applied to the text of the cell in my tests rather than the entire cell.
  • It's only TableRowSkinBase that does something different to ListCellSkin that's potentially relevant to this problem.

That difference mentioned in the second point is a call to setPickOnBounds(false). That isn't called for ListCell. Apparently the drop shadow increases the bounds of the cell causing it to overlap its adjacent cells and, since pick-on-bounds is true, that means the mouse hovers over the cell for longer than "expected".

Simply calling setPickOnBounds(false) on your custom list cells should fix the issue. For example:

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

Note: I do not know if calling setPickOnBounds(false) causes other issues or not.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...