Issue
I am trying to create a screen that consists entirely of a TabPane that fills the screen and that the content of the tab fills the tab. Here is what I have so far which creates a tab that fills the screen but when I add content to the tab nothing I have tried other than calculating and setting the width/height will work. I can write the code to do that but it is my firm belief that should be completely unnecessary as the whole point of a layout manager is to well calculate the layout according to a set of rules...
JavaFX Application:
public class TestFX extends Application
{
@Override
public void start(Stage stage) throws Exception
{
TabPane tPane = new TabPane();
tPane.setStyle("-fx-background-color : pink;");
tPane.getStyleClass().add("floating"); // Found this tip on SO already, if you remove it the tab won't fill the screen anymore.
tPane.getTabs().add(new Tab("Test Tab", new TestTabFX()));
Rectangle2D scrnRect = Screen.getPrimary().getVisualBounds();
stage.setX(scrnRect.getMinX() + scrnRect.getWidth() / 2);
stage.setY(scrnRect.getMinY());
stage.setWidth(scrnRect.getWidth() / 2);
stage.setHeight(scrnRect.getHeight());
Scene scene = new Scene(tPane);
stage.setTitle("Test Tabs");
stage.setScene(scene);
stage.show();
}
public static void main(String args[])
{
launch(args);
}
}
JavaFX component that will be the content of the tab:
public class TestTabFX extends Group
{
public TestTabFX()
{
TextField serverURL = new TextField("http://localhost:9090");
Button startServer = new Button("Start");
Button stopServer = new Button("Stop");
Button testServer = new Button("Test");
TextArea serverDetails = new TextArea();
HBox top = new HBox(10d, new Label("Server URL:"), serverURL, startServer, stopServer, testServer);
top.setStyle("-fx-background-color : red;");
GridPane tab = new GridPane();
tab.setStyle("-fx-background-color : green;");
tab.setBorder(new Border(new BorderStroke(Color.GREEN, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(7D))));
tab.addRow(0, top);
tab.addRow(1, serverDetails);
this.getChildren().add(tab);
}
}
PS I am fairly new to JavaFX but have used regular Java for many years which just adds to my frustration when I consider how easy it is to do with plain Java. What I want is the top collection of a TextField and Buttons to be centered and the TextArea to fill the screen. Both should resize appropriately if the screen resizes as well.
Any help would be appreciated.
Solution
As mentioned by Kleopatra, it is the choice of layout(s) that makes the difference. In your case, you want the content to be filled with the available space in the tab. The layout StackPane has this default behavior of extending to available space of its parent node. And for your information, the tab content region is already a StackPane which extends to the full available space. So it is your choice of layout and the appropriate properties will allow your content to fill the space.
For your reference, I have mentioned few layouts below. All the below layouts behave the same way. Please have a look of the appropriate properties that we set to behave as we want.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class TestFX extends Application {
@Override
public void start(Stage stage) throws Exception {
TabPane tPane = new TabPane();
tPane.setStyle("-fx-background-color : pink;");
tPane.getStyleClass().add("floating"); // Found this tip on SO already, if you remove it the tab won't fill the screen anymore.
tPane.getTabs().add(new Tab("Test Tab1", new TestTabFX1()));
tPane.getTabs().add(new Tab("Test Tab2", new TestTabFX2()));
tPane.getTabs().add(new Tab("Test Tab3", new TestTabFX3()));
Rectangle2D scrnRect = Screen.getPrimary().getVisualBounds();
stage.setX(scrnRect.getMinX() + scrnRect.getWidth() / 2);
stage.setY(scrnRect.getMinY());
stage.setWidth(scrnRect.getWidth() / 2);
stage.setHeight(scrnRect.getHeight());
Scene scene = new Scene(tPane);
stage.setTitle("Test Tabs");
stage.setScene(scene);
stage.show();
}
public static void main(String args[]) {
launch(args);
}
// EXTENDING STACKPANE : Has the default feature to fill the available space.
class TestTabFX1 extends StackPane {
public TestTabFX1() {
TextField serverURL = new TextField("http://localhost:9090");
Button startServer = new Button("Start");
Button stopServer = new Button("Stop");
Button testServer = new Button("Test");
TextArea serverDetails = new TextArea();
VBox.setVgrow(serverDetails, Priority.ALWAYS);
HBox top = new HBox(10d, new Label("Server URL:"), serverURL, startServer, stopServer, testServer);
top.setAlignment(Pos.CENTER);
VBox tab = new VBox(top, serverDetails);
tab.setSpacing(10);
tab.setPadding(new Insets(10));
getChildren().addAll(tab);
}
}
// EXTENDING VBOX : By using VGrow, you can make the layout to fill the available space
class TestTabFX2 extends VBox {
public TestTabFX2() {
TextField serverURL = new TextField("http://localhost:9090");
Button startServer = new Button("Start");
Button stopServer = new Button("Stop");
Button testServer = new Button("Test");
TextArea serverDetails = new TextArea();
VBox.setVgrow(serverDetails, Priority.ALWAYS);
HBox top = new HBox(10d, new Label("Server URL:"), serverURL, startServer, stopServer, testServer);
top.setAlignment(Pos.CENTER);
setSpacing(10);
setPadding(new Insets(10));
getChildren().addAll(top, serverDetails);
}
}
// EXTENDING GRIDPANE : By using column/row constraints, you can make the layout to fill the available space.
class TestTabFX3 extends GridPane {
public TestTabFX3() {
TextField serverURL = new TextField("http://localhost:9090");
Button startServer = new Button("Start");
Button stopServer = new Button("Stop");
Button testServer = new Button("Test");
TextArea serverDetails = new TextArea();
HBox top = new HBox(10d, new Label("Server URL:"), serverURL, startServer, stopServer, testServer);
top.setAlignment(Pos.CENTER);
addRow(0, top);
addRow(1,serverDetails);
ColumnConstraints cc = new ColumnConstraints();
cc.setHgrow(Priority.ALWAYS);
cc.setFillWidth(true);
getColumnConstraints().add(cc);
RowConstraints rc1 = new RowConstraints();
RowConstraints rc2 = new RowConstraints();
rc2.setVgrow(Priority.ALWAYS);
rc2.setFillHeight(true);
getRowConstraints().addAll(rc1,rc2);
setVgap(10);
setPadding(new Insets(10));
}
}
}
Answered By - Sai Dandem