java - TabView:左侧有一些选项卡,右侧有一些选项卡(中间有空格)
问题描述
我正在尝试在 JavaFX 中创建一个 TabView。我想让一些选项卡与其他选项卡保持距离,因为它们的功能属于另一个类别。
这就是它现在的样子:
如您所见,我希望将最后两个选项卡移到右侧而不影响其余选项卡。
这是我的 FXML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Application.MainController">
<center>
<VBox alignment="BOTTOM_CENTER" prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
<children>a
<TabPane accessibleRole="BUTTON" nodeOrientation="LEFT_TO_RIGHT" prefHeight="651.0" prefWidth="1000.0" tabClosingPolicy="UNAVAILABLE">
<tabs>
<Tab text="Courses">
<content>
<TableView prefHeight="665.0" prefWidth="1000.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</content>
</Tab>
<Tab text="Education Matrix">
<content>
<TableView prefHeight="200.0" prefWidth="200.0">
<columns>
<TableColumn prefWidth="75.0" text="C1" />
<TableColumn prefWidth="75.0" text="C2" />
</columns>
</TableView>
</content>
</Tab>
<Tab text="Employee">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab text="Calendar">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="companiesTab" text="Companies">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
<Tab fx:id="providerTab" text="Provider">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
</content>
</Tab>
</tabs>
<VBox.margin>
<Insets />
</VBox.margin>
</TabPane>
</children>
</VBox>
</center>
<bottom>
<GridPane prefHeight="105.0" prefWidth="1000.0" BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
<padding>
<Insets left="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER_RIGHT" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;" GridPane.columnIndex="2">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
<opaqueInsets>
<Insets />
</opaqueInsets>
<padding>
<Insets right="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" style="-fx-background-color: grey;" GridPane.columnIndex="1">
<children>
<Button mnemonicParsing="false" text="Button" />
</children>
</HBox>
</children>
</GridPane>
</bottom>
<top>
<GridPane prefHeight="106.0" prefWidth="1000.0" BorderPane.alignment="CENTER">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="494.0" minWidth="10.0" prefWidth="289.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="711.0" minWidth="10.0" prefWidth="711.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0">
<children>
<ChoiceBox prefWidth="150.0" />
</children>
<padding>
<Insets left="20.0" />
</padding>
</HBox>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" GridPane.columnIndex="1">
<children>
<Label text="Smart Academy Manager">
<font>
<Font name="Arial" size="31.0" />
</font>
</Label>
</children>
</HBox>
</children>
</GridPane>
</top>
</BorderPane>`enter code here`
解决方案
OriginalTabPane
不提供自定义选项卡布局的工具。但是使用一些技巧可以获得类似的结果。
您可以将不可见设置Tab
到所需位置并将其宽度与TabPane
.
首先我们需要计算拆分器的宽度。这是TabPane
减去Tab
s 的宽度之和的宽度,不包括拆分器。Tab
对象可以通过Node
使用TabPane
命令获得.lookup()
。我们还需要考虑与样式相关的宽度(填充、间距)。对于这个例子,我将通过硬设置这个数字(对于默认主题)。在计算之后,我们使用以下方法设置拆分器的大小.setStyle()
:
private void autoSizeSplitter(TabPane tabPane, Tab splitter) {
double width = tabPane.getWidth();
Set<Node> tabs = tabPane.lookupAll(".tab");
for (Node node : tabs) {
if (node.getId() == null || !node.getId().equals(splitter.getId())) {
width = width - node.getBoundsInParent().getWidth();
}
}
double PADDING = 20;
width = width - PADDING;
splitter.setStyle("-fx-background-color:transparent; -fx-pref-width: " + width + ";");
}
最后,我们TabPane
在初始化时第一次在 width 属性和 autosize splitter 上设置了监听器:
tabPane.widthProperty().addListener(observable -> autoSizeSplitter(tabPane, splitter));
Platform.runLater(() -> autoSizeSplitter(tabPane, splitter));
完整示例:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.Stage;
import java.util.Set;
public class Sample extends Application {
@Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
Tab splitter = new Tab();
splitter.setDisable(true);
splitter.setId("splitter");
tabPane.getTabs().add(new Tab("111"));
tabPane.getTabs().add(new Tab("222"));
tabPane.getTabs().add(splitter);
tabPane.getTabs().add(new Tab("333"));
tabPane.getTabs().add(new Tab("444"));
tabPane.getTabs().add(new Tab("555"));
Scene scene = new Scene(tabPane, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
tabPane.widthProperty().addListener(observable -> autoSizeSplitter(tabPane, splitter));
Platform.runLater(() -> autoSizeSplitter(tabPane, splitter));
}
private void autoSizeSplitter(TabPane tabPane, Tab splitter) {
double width = tabPane.getWidth();
Set<Node> tabs = tabPane.lookupAll(".tab");
for (Node node : tabs) {
if (node.getId() == null || !node.getId().equals(splitter.getId())) {
width = width - node.getBoundsInParent().getWidth();
}
}
double PADDING = 20;
width = width - PADDING;
splitter.setStyle("-fx-background-color:transparent; -fx-pref-width: " + width + ";");
}
public static void main(String[] args) {
launch(args);
}
}
推荐阅读
- javascript - 在 Javascript 中创建对象的方式有什么不同?
- laravel - 在 Nuxtjs 中使用 laravel-permission 根据角色隐藏菜单不起作用
- asp.net-core - 如何将 .NET 核心与 VS 2017 集成,或者它是否会默认与 VS 2017 一起提供?
- if-statement - ATS 证明:如果需要大于或等于,为什么这个静态?
- nlp - 从停用词过滤后查找二元组数
- react-native - React Native Gesture Handler 显示:undefined is not an object
- javascript - JS正确插入对象
- python - 无法使我的脚本产生特定的输出
- ios - 带有步骤进度的自定义进度视图
- azure-devops - 当实验主题和多阶段管道处于开启模式时,如何在自定义 azure devops 插件中添加自定义摘要选项卡?