Mark
Mark

Reputation: 2227

How to change the position of a RadioButton's label?

By default RadioButtons have their text label to the right of the button. I want the label to appear below the button instead. I found an old discussion on the Oracle forums but the solutions aren't great or just don't work.

I can create a custom component with a text-less radio button and a separate text label and position them as in a VBox. But then only the button itself responds to user events and not the whole thing.

Is there no simple way to reposition the label?

Upvotes: 1

Views: 4374

Answers (1)

DVarga
DVarga

Reputation: 21799

There is no "simple" way to do this (simple means setting a single property or something like this).

As a workaround you could do something like you mentioned with a VBox, but with a Label: You can set the RadioButton as the graphic of the Label and set the contentDisplayProperty to TOP (RadioButton is placed on top of the Label). And then you can add an event handler on the Label to select the RadioButton on click.

An example with this approach

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root, 400, 400);

            HBox hbox = new HBox();
            hbox.getChildren().add(createRadioLabel("Radio on the left", ContentDisplay.LEFT));
            hbox.getChildren().add(createRadioLabel("Radio on the top", ContentDisplay.TOP));
            hbox.getChildren().add(createRadioLabel("Radio on the bottom", ContentDisplay.BOTTOM));
            hbox.getChildren().add(createRadioLabel("Radio on the right", ContentDisplay.RIGHT));
            hbox.setSpacing(30);
            root.setCenter(hbox);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Label createRadioLabel(String text, ContentDisplay cd) {
        Label label = new Label(text);
        label.setGraphic(new RadioButton());
        label.setContentDisplay(cd);
        label.addEventHandler(MouseEvent.MOUSE_CLICKED, e -> {
            RadioButton radioButton = (RadioButton) ((Label) e.getSource()).getGraphic();
            radioButton.requestFocus();
            radioButton.setSelected(!radioButton.isSelected());

        });
        return label;
    }


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

And the produced RadioButtons:

enter image description here

Alternatively, if you want to have the text of the RadioButton rotated around the dot, you can use CSS rotations, with the attribute -fx-rotate:

.radio-button { -fx-rotate:180; }
.radio-button > .text { -fx-rotate: 180; }

The first selector will rotate the whole RadioButton, so as result the text will be placed on the left side of the "dot", upside down. The second selector rotates the text back to the normal direction.

Example

This example shows a RadioButton whose Text can be placed to any side of the "dot" specified by a ComboBox selection.

public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root, 400, 400);

            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());

            RadioButton rb = new RadioButton("In all directions);

            ComboBox<PseudoClass> combo = new ComboBox<>();
            combo.getItems().addAll(PseudoClass.getPseudoClass("left"), 
                    PseudoClass.getPseudoClass("top"),
                    PseudoClass.getPseudoClass("right"), 
                    PseudoClass.getPseudoClass("bottom"));

            combo.valueProperty().addListener((obs, oldVal, newVal) -> {

                if (oldVal != null)
                    rb.pseudoClassStateChanged(oldVal, false);

                rb.pseudoClassStateChanged(newVal, true);
            });

            root.setTop(combo);
            root.setCenter(rb);

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

application.css

.radio-button:left > .text { -fx-rotate: 180; }
.radio-button:left { -fx-rotate:180; }

.radio-button:right > .text { -fx-rotate: 0; }
.radio-button:right { -fx-rotate:0; }

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

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

And the displayed RadioButton:

enter image description here

Upvotes: 4

Related Questions