JavaFX:如何制作一个合适的垂直工具栏? [英] JavaFX: how to make a proper vertical toolbar?

查看:222
本文介绍了JavaFX:如何制作一个合适的垂直工具栏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个垂直排列的垂直工具栏。在Linux Mint中使用 JavaFX 2.2 包含在 JDK 7 中。



截图显示问题:





我使用的 FXML 看起来像这样:

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

<?language javascript?>

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

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

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

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

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

< / BorderPane>

我的定义中的正确工具栏是:按钮放置正确,工具栏宽度宽的按钮。蓝色表示工具栏当前的宽度。

解决方案

将旋转的工具项包装在一个组中,然后内置工具栏的布局将知道旋转是永久性的,应该考虑布局计算,而不仅仅是可能用于动画的临时事物。阅读。聚焦环的显示在CSS中定义,并包含背景插入显示的负值。结果是,当控制被聚焦时,它比没有聚焦时略大。通常,当您使用标准布局窗格时,这不是问题,因为布局窗格将忽略用于布局目的的背景插图。但是,组会考虑完整大小,并且不会忽略焦点响铃。结果是,仅包含控件的组在聚焦或未聚焦时会稍微改变大小。这给上面的解决方案带来了一个问题,因为当一个按钮变得聚焦时,它会稍微变大,并且工具栏中的布局会发生偏移,这是不理想的。



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



所以我们最终得到下面稍微详细的解决方案:





I want to make a vertical toolbar with buttons arranged vertically. Using JavaFX 2.2 that is included in JDK 7, in Linux Mint.

The screenshot shows the problem:

The FXML I am using looks like this:

<?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>

The proper toolbar in my definition is: buttons are placed correctly and the toolbar is as wide as the width of the buttons. The blue color indicates how wide the toolbar currently is.

解决方案

Wrap your rotated tool items in a Group, then the in-built layout of toolbar will know that the rotation is a permanent one which should be taken into account for layout calculations and not just a temporary thing which might be used for animations. Read the javadoc for Group, where it talks about layout bounds calculations to better understand this.

<?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>

Update 24th April 2017

The above solution is fine as far as it goes, but does suffer from an issue in that the buttons in the toolbar misalign when they receive focus.

What a group does is size itself based upon its contents. When the size of the contents changes, the size of the group also changes. When a button or control gets focus in JavaFX it gets a focus ring around the control. The display for the focus ring is defined in CSS and contains negative values for background inset display. The result is that, when a control is focused, it is slightly larger than when it is not focused. Normally, when you use a standard layout pane, this is not an issue as the layout pane will just ignore the background insets for layout purposes. A group however takes the full size into account and does not ignore the focus ring. The result is that a group that consists of only a control will change in size slightly when it is focused or unfocused. This presents an issue with the solution above because, when a button becomes focused, it will get slightly larger and the shift in layout in the toolbar, which is not ideal.

The solution to the focus shift problem in the above code is to just rotate the entire ToolBar within a group rather than rotating each button within a group per button. This works fine, but then presents some other issues such as the ToolBar not taking up the entire available area at the left side of the scene (due to wrapping it in a group removing the dynamic layout properties of the ToolBar). To get around this, a binding in code can be used to size the ToolBar to the available area of its parent layout container.

So we end up with the slightly more verbose solution below:

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);
    }

}

Notes:

  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());
    


An alternate solution to the focus issue (using CSS to remove the focus ring entirely), is presented in:

这篇关于JavaFX:如何制作一个合适的垂直工具栏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆