根据 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;
}
这就是结果:
如您所见,第一个选项卡中的表格具有焦点,但该选项卡具有绿色边框,而不是红色边框。有人能说一下如何解决吗?还是我误解了这个伪类的含义?
focus-within
psuedoclass 的文档说:
当
变量为 true 时适用focusWithin
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;
}