JavaFX:如何制作一个合适的垂直工具栏?

3
我想创建一个垂直工具栏,其中包含垂直排列的按钮。在Linux Mint中使用包含在JDK 7中的JavaFX 2.2。
以下是此问题的屏幕截图: enter image description here 我正在使用的FXML如下所示:
<?xml version="1.0" encoding="UTF-8"?>

<?language javascript?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane prefHeight="800.0" prefWidth="700.0" styleClass="root" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <top>
        <ToolBar>
            <items>
                <Button text="Test" />
            </items>
        </ToolBar>

    </top>
    <left>
        <ToolBar orientation="VERTICAL" style="-fx-background-color: blue;">
            <items>

                        <Region style="-fx-padding:10;" />
                        <Button rotate="-90" text="Project" style="-fx-label-padding:1;"/>
                        <Region style="-fx-padding:10;" />
                        <Button rotate="-90" text="Structure" />

            </items>
        </ToolBar>
    </left>
    <center>
        <HBox>
            <children>
            </children>
        </HBox>
    </center>
    <bottom>
        <ToolBar prefHeight="18.0" prefWidth="472.0">
            <items>
                <Region styleClass="spacer" />
                <HBox>
                    <children>

                    </children>
                </HBox>
            </items>
        </ToolBar>
    </bottom>

</BorderPane>

我的定义中,正确的工具栏应该是:按钮放置正确,工具栏宽度与按钮宽度相同。蓝色表示当前工具栏的宽度。
1个回答

9
将旋转的工具项放入一个Group中,这样工具栏的内置布局就会知道旋转是一种永久性的变化,需要考虑到布局计算,而不仅仅是临时的动画效果。请阅读Group的javadoc,了解更多关于布局边界计算的内容。

tools

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>


<HBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="200.0" prefWidth="100.0" style="-fx-background-color: cornsilk;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <ToolBar orientation="VERTICAL" style="-fx-base: palegreen;">
        <items>
            <Group>
               <children>
                <Button rotate="-90.0" style="-fx-base: gold;" text="Project" />
               </children>
            </Group>
            <Group>
               <children>
                  <Button rotate="-90.0" style="-fx-base: khaki;" text="Structure" />
               </children>
            </Group>
        </items>
      </ToolBar>
   </children>
</HBox>

2017年4月24日更新

以上解决方案在一定程度上是可行的,但存在一个问题:当工具栏按钮获得焦点时,它们会对齐不准。

所谓组是指根据其内容自动调整大小的容器。当内容的大小发生变化时,组的大小也会随之改变。当JavaFX中的按钮或控件获得焦点时,它会在控件周围显示一个焦点环。焦点环的显示由CSS定义,并包含负值来显示背景插入。结果是,当控件获得焦点时,它比未获得焦点时略微大一些。通常情况下,当您使用标准布局面板时,这不是问题,因为布局面板将仅忽略背景插入以进行布局。然而,组会考虑整个大小,并且不会忽略焦点环。结果是,只包含一个控件的组在聚焦或失焦时会略微改变大小。这导致了上述解决方案的问题,因为当一个按钮获得焦点时,它会变得稍微大一些,从而导致工具栏的布局移位,这是不理想的。

解决上述代码中焦点移位问题的方法是将整个工具栏旋转到组内,而不是每个按钮旋转到组内。这样做可以正常工作,但会出现其他问题,例如工具栏没有占用场景左侧的整个可用区域(因为将其包装在组中会删除工具栏的动态布局属性)。为了解决这个问题,可以在代码中使用绑定来将工具栏的大小调整为其父布局容器的可用区域。

因此,我们最终得到了下面略微冗长的解决方案:

focusedtooldisplay

skinsample/toolbar.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.control.ToolBar?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>

<?import javafx.scene.control.ToggleGroup?>
<BorderPane fx:id="border" prefHeight="200.0" prefWidth="100.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="skinsample.VerticalToolbarController">
   <left>
     <Group>
       <fx:define>
         <ToggleGroup fx:id="selectedTool"/>
       </fx:define>
       <ToolBar fx:id="toolbar" rotate="-90.0" style="-fx-base: palegreen;">
         <Pane HBox.hgrow="ALWAYS" />
         <ToggleButton style="-fx-base: khaki;" text="Structure" toggleGroup="${selectedTool}"/>
         <ToggleButton style="-fx-base: gold;" text="Project" toggleGroup="${selectedTool}" selected="true"/>
       </ToolBar>
     </Group>
   </left>
</BorderPane>

skinsample/VerticalToolbarController.java

package skinsample;

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.scene.control.ToolBar;
import javafx.scene.layout.BorderPane;

public class VerticalToolbarController {

    @FXML
    private BorderPane border;

    @FXML
    private ToolBar toolbar;

    public void initialize() {
        toolbar.minWidthProperty().bind(Bindings.max(border.heightProperty(), toolbar.prefWidthProperty()));
    }
}

skinsample/ToolDisplayApp.java

package skinsample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class ToolDisplayApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("toolbar.fxml"));
        Scene scene = new Scene(loader.load());
        stage.setScene(scene);
        stage.show();
    }

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

}

注意:

  1. This solution also demonstrates use of ToggleButtons rather than standard buttons within the ToolBar.
  2. We also eliminate the default overflow behavior of the ToolBar (as it seems a little annoying in the vertical toolbar situation), using:

    toolbar.minWidthProperty().bind(Bindings.max(border.heightProperty(), toolbar.prefWidthProperty()));
    
  3. If you want to retain the overflow behavior, then use:

    toolbar.prefWidthProperty().bind(border.heightProperty());
    

解决焦点问题的另一种方法(使用CSS完全删除焦点环),见:


<Pane HBox.hgrow="ALWAYS" /> 用于工具栏中项目的对齐:请参阅如何在Java FX工具栏中右对齐按钮以获取解释。如果您不需要进行任何其他对齐,则可以省略它。 - jewelsea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接