伪类 focus-within 不适用于 JavaFX 中的选项卡

问题描述 投票:0回答:1

根据 https://openjfx.io/javadoc/22/javafx.graphics/javafx/scene/doc-files/cssref.html JavaFX 22 支持伪类

focus-within
。我使用 JavaFX 23-ea+3,这是我的代码:

public class JavaFxTest7 extends Application {

    private static class Student {

        private int id;

        private int mark;

        public Student(int id, int mark) {
            this.id = id;
            this.mark = mark;
        }

        public int getId() {
            return id;
        }

        public int getMark() {
            return mark;
        }
    }

    private static class MyTab extends Tab {

        private final TableView<Student> table = new TableView<>(FXCollections.observableList(
            List.of(new Student(1, 3), new Student(2, 4), new Student(3, 5))));

        private final MenuItem menuItem = new MenuItem("New Tab");

        private final ContextMenu contextMenu = new ContextMenu(menuItem);

        public MyTab() {
            var idColumn = new TableColumn<Student, Integer>();
            idColumn.setCellValueFactory((data) ->  new ReadOnlyObjectWrapper<>(data.getValue().getId()));
            var markColumn = new TableColumn<Student, Integer>();
            markColumn.setCellValueFactory((data) ->  new ReadOnlyObjectWrapper<>(data.getValue().getMark()));
            table.getColumns().addAll(idColumn, markColumn);
            menuItem.setOnAction((e) -> {
                var newTab = new MyTab();
                this.getTabPane().getTabs().add(newTab);
            });
            table.setContextMenu(contextMenu);
            this.setContent(table);
        }

    }

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        TabPane tabPane = new TabPane();
        tabPane.getTabs().add(new MyTab());
        var scene = new Scene(tabPane, 400, 300);
        var css= this.getClass().getResource("test7.css").toExternalForm();
        scene.getStylesheets().add(css);
        stage.setScene(scene);
        stage.show();
    }
}

和test7.css:

.tab-pane > .tab-header-area .tab .focus-indicator {
    -fx-border-width: 2 0 0 0;
    -fx-border-color: green;
    -fx-border-insets: -3 -5 0 -5;
    -fx-border-radius: 2 2 0 0;
}

.tab-pane > .tab-header-area .tab:focus-within .focus-indicator {
    -fx-border-width: 2 0 0 0;
    -fx-border-color: red;
    -fx-border-insets: -3 -5 0 -5;
    -fx-border-radius: 2 2 0 0;
}

这就是结果:

如您所见,第一个选项卡中的表格具有焦点,但该选项卡具有绿色边框,而不是红色边框。有人能说一下如何解决吗?还是我误解了这个伪类的含义?

java javafx javafx-css
1个回答
1
投票

focus-within
psuedoclass 的文档说:

focusWithin
变量为 true 时适用

并注意

focusWithin
Node
的属性,但
Tab
不是
Node
的子类,因此它没有这样的属性。 (
Tab
实际上是
TabPane
数据模型的一部分;它实际上并不是 MVC 意义上的 UI/View 类。)

Tab
确实有一个
selected
属性,它被传播到 CSS 伪类(尽管我无法立即找到后半部分的文档)。并且
TabPane
是一个
Node
,因此您可以在选项卡窗格上使用
focus-within
伪类。以下内容可以满足您的需要:

.tab-pane > .tab-header-area .tab .focus-indicator {
    -fx-border-width: 2 0 0 0;
    -fx-border-color: green;
    -fx-border-insets: -3 -5 0 -5;
    -fx-border-radius: 2 2 0 0;
}

.tab-pane:focus-within > .tab-header-area .tab:selected .focus-indicator {
    -fx-border-width: 2 0 0 0;
    -fx-border-color: red;
    -fx-border-insets: -3 -5 0 -5;
    -fx-border-radius: 2 2 0 0;
}

顺便说一句,一个稍微优雅的解决方案(可以说)是使用查找的颜色:

.tab-pane > .tab-header-area .tab .focus-indicator {
    -fx-border-width: 2 0 0 0;
    -my-tab-border-color: green;
    -fx-border-color: -my-tab-border-color;
    -fx-border-insets: -3 -5 0 -5;
    -fx-border-radius: 2 2 0 0;
}

.tab-pane:focus-within > .tab-header-area .tab:selected .focus-indicator {
    -my-tab-border-color: red;
}

© www.soinside.com 2019 - 2024. All rights reserved.