JavaFX - 仅样式第一个和最后一个选项卡
JavaFX - Style first and last tab only
有没有办法(CSS 或 Java)仅在 dynamic TabPane
中设置第一个和最后一个选项卡的样式?
示例:
谢谢!
可以适当观察每个Tab
的TabPane#getTabs()
and update the style class返回的ObservableList<Tab>
。例如:
App.java:
import javafx.application.Application;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.css.Styleable;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.control.TabPane.TabDragPolicy;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
TabPane pane = new TabPane();
pane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
pane.setTabDragPolicy(TabDragPolicy.REORDER); // requires JavaFX 10+
pane.getTabs().addListener(App::tabsChanged);
pane.getTabs() // add tabs **after** adding ListChangeListener
.addAll(
new Tab("Test Tab #1", new StackPane(new Label("Content #1"))),
new Tab("Test Tab #2", new StackPane(new Label("Content #2"))),
new Tab("Test Tab #3", new StackPane(new Label("Content #3"))),
new Tab("Test Tab #4", new StackPane(new Label("Content #4"))),
new Tab("Test Tab #5", new StackPane(new Label("Content #5"))));
Scene scene = new Scene(pane, 600, 400);
scene.getStylesheets().add(getClass().getResource("/App.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
private static void tabsChanged(Change<? extends Tab> c) {
while (c.next()) {
if (c.wasRemoved()) {
for (Tab removed : c.getRemoved()) {
removed.getStyleClass().removeAll("first-tab", "last-tab");
}
}
}
ObservableList<? extends Tab> tabs = c.getList();
if (tabs.size() == 1) {
Tab tab = tabs.get(0);
addStyleClassIfAbsent(tab, "first-tab");
addStyleClassIfAbsent(tab, "last-tab");
} else if (!tabs.isEmpty()) {
Tab first = tabs.get(0);
addStyleClassIfAbsent(first, "first-tab");
first.getStyleClass().remove("last-tab");
Tab last = tabs.get(tabs.size() - 1);
addStyleClassIfAbsent(last, "last-tab");
last.getStyleClass().remove("first-tab");
for (Tab middle : tabs.subList(1, tabs.size() - 1)) {
middle.getStyleClass().removeAll("first-tab", "last-tab");
}
}
}
private static void addStyleClassIfAbsent(Styleable styleable, String styleClass) {
ObservableList<String> styleClasses = styleable.getStyleClass();
if (!styleClasses.contains(styleClass)) {
styleClasses.add(styleClass);
}
}
}
App.css:
.first-tab,
.last-tab {
-fx-base: pink;
}
-fx-base
是由 modena.css
添加的 looked-up color(即 JavaFX 8+ 中的默认用户代理样式表)。我设置它而不是 -fx-background-color
属性 以便连接到 modena.css
提供的 "theming"。在上面的示例中,您可以看到样式通过鼠标拖动 (JavaFX 10+) 重新排序选项卡或关闭选项卡来动态更改。
请注意,我更愿意为此使用 PseudoClass
。但是,据我所知,Tab
class 不允许您直接(取消)激活伪 classes。它处理 :selected
伪 class 的方式在 TabPane
的默认皮肤内部,这意味着我们无法从外部出于我们的目的可靠地访问相同的功能。
有没有办法(CSS 或 Java)仅在 dynamic TabPane
中设置第一个和最后一个选项卡的样式?
示例:
谢谢!
可以适当观察每个Tab
的TabPane#getTabs()
and update the style class返回的ObservableList<Tab>
。例如:
App.java:
import javafx.application.Application;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.css.Styleable;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.control.TabPane.TabDragPolicy;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
TabPane pane = new TabPane();
pane.setTabClosingPolicy(TabClosingPolicy.ALL_TABS);
pane.setTabDragPolicy(TabDragPolicy.REORDER); // requires JavaFX 10+
pane.getTabs().addListener(App::tabsChanged);
pane.getTabs() // add tabs **after** adding ListChangeListener
.addAll(
new Tab("Test Tab #1", new StackPane(new Label("Content #1"))),
new Tab("Test Tab #2", new StackPane(new Label("Content #2"))),
new Tab("Test Tab #3", new StackPane(new Label("Content #3"))),
new Tab("Test Tab #4", new StackPane(new Label("Content #4"))),
new Tab("Test Tab #5", new StackPane(new Label("Content #5"))));
Scene scene = new Scene(pane, 600, 400);
scene.getStylesheets().add(getClass().getResource("/App.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
private static void tabsChanged(Change<? extends Tab> c) {
while (c.next()) {
if (c.wasRemoved()) {
for (Tab removed : c.getRemoved()) {
removed.getStyleClass().removeAll("first-tab", "last-tab");
}
}
}
ObservableList<? extends Tab> tabs = c.getList();
if (tabs.size() == 1) {
Tab tab = tabs.get(0);
addStyleClassIfAbsent(tab, "first-tab");
addStyleClassIfAbsent(tab, "last-tab");
} else if (!tabs.isEmpty()) {
Tab first = tabs.get(0);
addStyleClassIfAbsent(first, "first-tab");
first.getStyleClass().remove("last-tab");
Tab last = tabs.get(tabs.size() - 1);
addStyleClassIfAbsent(last, "last-tab");
last.getStyleClass().remove("first-tab");
for (Tab middle : tabs.subList(1, tabs.size() - 1)) {
middle.getStyleClass().removeAll("first-tab", "last-tab");
}
}
}
private static void addStyleClassIfAbsent(Styleable styleable, String styleClass) {
ObservableList<String> styleClasses = styleable.getStyleClass();
if (!styleClasses.contains(styleClass)) {
styleClasses.add(styleClass);
}
}
}
App.css:
.first-tab,
.last-tab {
-fx-base: pink;
}
-fx-base
是由 modena.css
添加的 looked-up color(即 JavaFX 8+ 中的默认用户代理样式表)。我设置它而不是 -fx-background-color
属性 以便连接到 modena.css
提供的 "theming"。在上面的示例中,您可以看到样式通过鼠标拖动 (JavaFX 10+) 重新排序选项卡或关闭选项卡来动态更改。
请注意,我更愿意为此使用 PseudoClass
。但是,据我所知,Tab
class 不允许您直接(取消)激活伪 classes。它处理 :selected
伪 class 的方式在 TabPane
的默认皮肤内部,这意味着我们无法从外部出于我们的目的可靠地访问相同的功能。