Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX 2 buttons size fill width and are each same width?

Tags:

java

javafx-2

Working in Java FX 2.2. The Scene has a horizontal width that is fixed but is unknown at compile time. I want to place 2 or more buttons in a horizontal row that completely fills the horizontal space in the Scene AND that are each exactly the same width. The number of buttons changes dynamically with the program state. What program snippet will accomplish this?

like image 864
Don Wills Avatar asked Oct 11 '12 00:10

Don Wills


2 Answers

A bit cleaner solution with property binding:

    HBox buttonLayout = new HBox();
    buttonLayout.getChildren().add(button1);
    buttonLayout.getChildren().add(button2);

    int btnCount = buttonLayout.getChildren().size();
    button1.prefWidthProperty().bind(buttonLayout.widthProperty().divide(btnCount));
    button2.prefWidthProperty().bind(buttonLayout.widthProperty().divide(btnCount));
like image 189
RainHunter Avatar answered Nov 04 '22 17:11

RainHunter


This code from the HBox javadoc will almost do what you want, except that "buttons themselves are different sizes based on the text contained in the button - wider text causes wider buttons".

HBox hbox = new HBox();
Button button1 = new Button("Add");
Button button2 = new Button("Remove");
HBox.setHgrow(button1, Priority.ALWAYS);
HBox.setHgrow(button2, Priority.ALWAYS);
button1.setMaxWidth(Double.MAX_VALUE);
button2.setMaxWidth(Double.MAX_VALUE);
hbox.getChildren().addAll(button1, button2);

By creating a custom layout pane based on HBox and overriding it's layout method, you can get exactly the behaviour you describe.

import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.stage.Stage;

// displays equal width buttons which fill a layout region's width.
// http://stackoverflow.com/questions/12830402/javafx-2-buttons-size-fill-width-and-are-each-same-width
public class HorizontallyTiledButtons extends Application {
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage stage) {
    final Button addButton    = new Button("Add");
    final Button removeButton = new Button("Remove");
    final Button extraButton  = new Button("The wizard of Frobozz is watching");

    final ButtonBar buttonBar = new ButtonBar(5, addButton, removeButton);

    addButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        buttonBar.addButton(extraButton);
      }
    });

    removeButton.setOnAction(new EventHandler<ActionEvent>() {
      @Override public void handle(ActionEvent event) {
        buttonBar.removeButton(extraButton);
      }
    });

    VBox layout = new VBox(10);
    layout.getChildren().addAll(buttonBar);
    layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");

    stage.setScene(new Scene(layout));
    stage.setWidth(800);
    stage.show();
  }

  class ButtonBar extends HBox {
    ButtonBar(double spacing, Button... buttons) {
      super(spacing);
      getChildren().addAll(buttons);
      for (Button b: buttons) {
        HBox.setHgrow(b, Priority.ALWAYS);
        b.setMaxWidth(Double.MAX_VALUE);
      }
    }

    public void addButton(Button button) {
      HBox.setHgrow(button, Priority.ALWAYS);
      button.setMaxWidth(Double.MAX_VALUE);
      ObservableList<Node> buttons = getChildren();
      if (!buttons.contains(button)) {
        buttons.add(button);
      }
    }

    public void removeButton(Button button) {
      getChildren().remove(button);
    }

    @Override protected void layoutChildren() {
      double minPrefWidth = calculatePrefChildWidth();
      for (Node n: getChildren()) {
        if (n instanceof Button) {
          ((Button) n).setMinWidth(minPrefWidth);
        }
      }
      super.layoutChildren();
    }

    private double calculatePrefChildWidth() {
      double minPrefWidth = 0;
      for (Node n: getChildren()) {
        minPrefWidth = Math.max(minPrefWidth, n.prefWidth(-1));
      }
      return minPrefWidth;
    }
  }
}

Sample program output: twobuttonsthreebuttons

like image 30
jewelsea Avatar answered Nov 04 '22 17:11

jewelsea