CSS 查找本质上依赖于渲染框架的实现细节,因此它们可能不可靠,您应该尽可能避免使用它们。特别是,如果尚未在场景图上进行 CSS 传递(通常在渲染期间发生),或者自上次 CSS 传递后发生 CSS 状态更改,则查找将不起作用。我认为您的代码发生的事情是在使用新的选择状态更新 CSS 状态之前调用了侦听器,导致您Tab
从.tab:selected
查找中检索错误(尽管我不确定这是正在发生的事情) .
请注意,您已经拥有了大部分所需的动态行为,因为"selected"
伪类将动态更新。
实现此类功能的最佳方法是定义一个涵盖所有可能样式的外部 CSS 文件,然后使用多种机制之一以编程方式修改 CSS 状态。有几种方法可以做到这一点:
- 使用“查找颜色”。这些就像 CSS 中的变量名一样。
- 使用自定义伪类,您可以将其用作 CSS 文件中的选择器,并且您可以通过编程方式更新其状态。
这是使用第一种方法的示例。在这里,我们在名为的 CSS 文件中定义了一种查找颜色,"selected-tab-color"
它最初将关闭按钮设置为蓝色。
tabpane.css:
.tab-pane {
selected-tab-color: blue ;
}
.tab:selected > .tab-container > .tab-close-button {
-fx-background-color: selected-tab-color ;
}
在Java 代码中,我们可以简单地通过调用来更新tabPane.setStyle("selected-tab-color: red;")
它,您可以在例如事件处理程序中执行此操作(但实际上在任何地方,只要它在JavaFX 应用程序线程上)。在这个例子中,我们只是列出了选定的选项卡,并让一个选项卡有一个红色的关闭按钮,其他的蓝色。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TabPaneTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TabPane tabPane = new TabPane();
Tab tab1 = new Tab("Tab 1", new Label("Tab 1"));
Tab tab2 = new Tab("Tab 2", new Label("This tab has\na custom close button"));
Tab tab3 = new Tab("Tab 3", new Label("Tab 3"));
tabPane.getTabs().addAll(tab1, tab2, tab3);
tabPane.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) -> {
if (newTab == tab2) {
tabPane.setStyle("selected-tab-color: red;");
} else {
tabPane.setStyle("selected-tab-color: blue;");
}
});
BorderPane root = new BorderPane(tabPane);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("tabpane.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setWidth(250);
primaryStage.setHeight(250);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
您可以使用此技术通过恢复为默认值来完全关闭效果:
tabPane.setStyle("selected-tab-color: -fx-mark-color;");
然而,这依赖于了解默认 CSS 实现的细节(即选项卡关闭按钮的默认颜色名称)。
以编程方式打开或关闭功能的更好方法是使用自定义 Pseudoclass。它们像任何其他 CSS 伪类一样工作,并且可以通过编程方式修改它们的状态。
warn-on-close
在此示例中,仅当包含选项卡窗格具有伪类集时,关闭按钮的颜色才为红色:
.tab-pane:warn-on-close .tab:selected > .tab-container > .tab-close-button {
-fx-background-color: red ;
}
在此处的 Java 代码中,我们在选择选项卡 2 时将其打开,并在选择其他选项卡时关闭。同样,这里可以使用任意逻辑。
import javafx.application.Application;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TabPaneTest extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
TabPane tabPane = new TabPane();
Tab tab1 = new Tab("Tab 1", new Label("Tab 1"));
Tab tab2 = new Tab("Tab 2", new Label("This tab has\na custom close button"));
Tab tab3 = new Tab("Tab 3", new Label("Tab 3"));
tabPane.getTabs().addAll(tab1, tab2, tab3);
PseudoClass warnOnClosePseudoClass = PseudoClass.getPseudoClass("warn-on-close");
tabPane.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) ->
tabPane.pseudoClassStateChanged(warnOnClosePseudoClass, newTab == tab2));
BorderPane root = new BorderPane(tabPane);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("tabpane.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setWidth(250);
primaryStage.setHeight(250);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}