简体   繁体   中英

Divide stage into 2 gridpanes JavaFX

So Im trying to have text on the left and buttons on the right, text should have constant size and buttons should resize to fill the rest of the window.

Here is my result so far:

至今...

I dont want my text over buttons, I want them to share the whole window.

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;


public class Main extends Application {

    GridPane buttons = new GridPane();
    GridPane textGrid = new GridPane();
    @Override
    public void start(Stage primaryStage) {

       StackPane root = new StackPane();
       Button button1 = new Button();
       Button button2 = new Button();
       Button button3 = new Button();
       Button button4 = new Button();
       Button button5 = new Button();

       button1.setText("Button1");
       button2.setText("Button4");
       button3.setText("Button3");
       button4.setText("Button4");
       button5.setText("Button5");


       TextArea text1 = new TextArea();
       text1.setText("Test");
       text1.setPrefSize(100, 100);

       button1.prefWidthProperty().bind(buttons.widthProperty());
       button2.prefWidthProperty().bind(buttons.widthProperty());
       button3.prefWidthProperty().bind(buttons.widthProperty());
       button4.prefWidthProperty().bind(buttons.widthProperty());
       button5.prefWidthProperty().bind(buttons.widthProperty());

       button1.prefHeightProperty().bind(buttons.heightProperty());
       button2.prefHeightProperty().bind(buttons.heightProperty());
       button3.prefHeightProperty().bind(buttons.heightProperty());
       button4.prefHeightProperty().bind(buttons.heightProperty());
       button5.prefHeightProperty().bind(buttons.heightProperty());


       buttons.addColumn(0, button1, button2, button3, button4, button5);

       textGrid.addColumn(0, text1);


        Scene scene = new Scene(root, 280, 180);

        root.getChildren().addAll(buttons, textGrid);

        buttons.setAlignment(Pos.TOP_RIGHT);
        textGrid.setAlignment(Pos.TOP_LEFT); 

        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

}

It is usually better to let the layout panes handle the layout management rather than trying to manage the layout through bindings.

Here is a sample:

布局

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.stream.IntStream;

public class Main extends Application {

    private static final int N_BUTTONS = 5;

    @Override
    public void start(Stage stage) {
        VBox buttonLayout = new VBox(
                10,
                IntStream.range(0, N_BUTTONS)
                        .mapToObj(this::createButton)
                        .toArray(Button[]::new)
        );
        HBox.setHgrow(buttonLayout, Priority.ALWAYS);

        TextArea textArea = new TextArea("Test");
        textArea.setPrefWidth(100);
        textArea.setMaxWidth(TextArea.USE_PREF_SIZE);
        textArea.setMinWidth(TextArea.USE_PREF_SIZE);

        HBox layout = new HBox(10, textArea, buttonLayout);
        layout.setPadding(new Insets(10));

        Scene scene = new Scene(layout);

        stage.setScene(scene);
        stage.show();
    }

    private Button createButton(int i) {
        Button button = new Button("Button " + i);
//        button.setMaxWidth(Double.MAX_VALUE);
        button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
        VBox.setVgrow(button, Priority.ALWAYS);

        return button;
    }

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

Here are a couple of things I would point out based upon the sample:

  1. As the buttons are so similar, create the buttons in a loop rather than individually in code. I use an IntStream range with a map and a toArray , but you could do the same thing with a standard for loop (which may be easier to understand).
  2. Use combinations of standard layout panes to achieve your layout. For example the buttons are vertically spaced, so put them in a VBox, the text and the buttons are horizontal to each other, so use a HBox.
  3. Use constraints on the layouts to massage them into performing the layout you like, for example, HBox.setHgrow(buttonLayout, Priority.ALWAYS); tells the Box to always assign any extra additional space in the Box to the buttonLayout so that the buttons will fill any remaining area.
  4. Set constraints on the individual nodes to size them how you wish, for example the following code establishes a fixed width for the textArea, which will not vary (you could similar code to establish a fixed height if you wished):

     textArea.setPrefWidth(100); textArea.setMaxWidth(TextArea.USE_PREF_SIZE); textArea.setMinWidth(TextArea.USE_PREF_SIZE); 
  5. Some controls will automatically expand themselves beyond their max size, buttons do not by default, to enable this behavior use the following code (if you only wanted the width to expand and not the height then you would only set the maxWidth rather than the maxSize):

     button.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); 
  6. Rather than defining layouts in code as in this example, instead use a tool such as SceneBuilder to create the scene visually and save the layout as an FXML file , so that the layout is separated from your code (similarly place any styling in an external CSS file).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM