user3237736
user3237736

Reputation: 857

JavaFX / FXML: Vertical button alongside the entire window

I'm using a GridPane as the main scene of my stage, the layout is entirely defined in an FXML file. I want to have a button accross the entire side of the window (i.e. accross all rows of my GridPane), as follows:

enter image description here

However I just can't get it to work. More precisely, it seems the button just won't strecht accross the entire height. I've set GridPane.vgrow=ALWAYS, maxHeight="Infinity", and GridPane.fillHeight=true for the button, but still the button is just as long as the text in it, and placed in the center of the side.

How can I get the button to stretch across the entire GridPane? As mentioned in the beginning, of course I've set the GridPane.rowSpan correctly. It's not that the button is not placed correctly in the GridPane, it's just that it won't strecht itself accross the entire available vertical space.

And please note I would prefer a solution via FXML, not Java code, because I wouldn't want to have such layouting code in my classes.

Thank you!

Upvotes: 0

Views: 1641

Answers (3)

ItachiUchiha
ItachiUchiha

Reputation: 36722

Easiest way to do this would be to use css. Follow the following steps:

To rotate the label used in the button, use :

.button > .text {
    -fx-rotate: 90;
}

For extending the button to use the entire height, use Infinity as preferred height :

.button {
    -fx-pref-height: Infinity;
    -fx-pref-width: 75;
}

MCVE

Here is an example, which shows how to use the above code :

FXML

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>

<GridPane styleClass="root" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
   <columnConstraints>
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
   </columnConstraints>
   <rowConstraints>
      <RowConstraints minHeight="50.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="50.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="50.0" prefHeight="30.0" vgrow="SOMETIMES" />
   </rowConstraints>
   <children>
      <Button mnemonicParsing="false" text="Button" GridPane.rowSpan="3" />
      <VBox style="-fx-background-color: white;" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS" />
      <VBox style="-fx-background-color: white;" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" />
      <VBox style="-fx-background-color: white;" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" />
   </children>
</GridPane>

CSS

root is the style-class assigned to GridPane.

.root {
    -fx-background-color: grey;
    -fx-hgap: 5;
    -fx-vgap: 5;
    -fx-padding: 5;
}

.root > .button > .text {
    -fx-rotate: 90;
}

.button {
    -fx-pref-height: Infinity;
    -fx-pref-width: 75;
}

Main

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

public class Main extends Application {

    @Override
    public void start(final Stage primaryStage) throws Exception {

        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/grid.fxml"));
        final Parent root = fxmlLoader.load();
        final Scene scene = new Scene(root, 685, 411);
        scene.getStylesheets().add(getClass().getResource("/grid.css").toExternalForm());
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

OUTPUT

enter image description here

Upvotes: 4

GOXR3PLUS
GOXR3PLUS

Reputation: 7255

Select the Vertical Button.

In SceneViewer go to Layout Drop Down.

1.Set minHeight,minWidth,prefWidth,prefHeight,MaxWidth

            to 
   **USE_COMPUTED_SIZE**

and maxHeight

            to
      **MAX_VALUE**

2.The Button has to span all the rows of GridPane.

3.The Button has to be rotated by 90 degree

Note also something important here.When you resize a column or row in SceneViewer the size you set will be the maximum size.

This might add problems cause if the window grows the GridPane will not go accordingly.

So select all the columns and rows and be soore that the max size is set to

USE_COMPUTED_SIZE if you want them to grow.I added this just as advice.

Upvotes: 0

ali shreef
ali shreef

Reputation: 89

it is a good question man. it was hard to figure out to do it but here the result and FXML file that scene builder make to do this :

enter image description here

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>

<GridPane hgap="20.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" vgap="5.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
  <columnConstraints>
    <ColumnConstraints halignment="CENTER" hgrow="NEVER" maxWidth="100.0" minWidth="50.0" prefWidth="100.0" />
    <ColumnConstraints hgrow="NEVER" maxWidth="1.7976931348623157E308" minWidth="500.0" prefWidth="500.0" />
  </columnConstraints>
  <rowConstraints>
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
  </rowConstraints>
   <children>
      <Label text="Label" GridPane.columnIndex="1" />
      <Label text="Label" GridPane.columnIndex="1" GridPane.rowIndex="1" />
      <Label text="Label" GridPane.columnIndex="1" GridPane.rowIndex="2" />
      <AnchorPane GridPane.hgrow="ALWAYS" GridPane.rowSpan="3" GridPane.vgrow="ALWAYS">
         <children>
            <Button contentDisplay="TOP" mnemonicParsing="false" textOverrun="CLIP" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
               <font>
                  <Font size="11.0" />
               </font>
               <graphic>
                  <Label minWidth="-Infinity" rotate="90.0" text="Some Text">
                     <font>
                        <Font size="15.0" />
                     </font>
                  </Label>
               </graphic>
            </Button>
         </children>
      </AnchorPane>
   </children>
</GridPane>

Here what i have done: I put Gridepane as parent for other controller , it contain 2 column and 3 row for example ,then i put anchor pane and index (0,0) and make column span to remain and put other component as you want in other rows, then i but button in anchor pane and set value of anchor pane constrain to 0 for all corner (you can find anchor pane constrain under layout section of button) after that I delete the text of the button and put label with text in button , finally i rotated the label 90 degree (you can find rotate property under transformation at layout of label) and then you got what you want .

i hope that i answer to your question!

Upvotes: 1

Related Questions