Align a label with textarea - javafx

How can I align the position of my "Description" label such that it corresponds in line with the "Enter description" text (Label - TextArea). These components are inside an gridPane and coded in javaFX ( so no Scene Builder tips can help me here ).
Code:
Label descriptionLabel = new Label("Description:");
descriptionLabel.setPadding(new Insets(5, 5, 5, 5));
JFXTextArea descriptionTextArea = new JFXTextArea();
descriptionTextArea.setPadding(new Insets(5, 0, 5, 0));
descriptionTextArea.setPromptText("Enter description...");
gridPane.add(descriptionLabel, 0, 2);
gridPane.add(descriptionTextArea, 1, 2);
I've tried with descriptionLabel.setAlignment(Pos.TOP_LEFT); but neither that helped me out

You have to use GridPane Constraints. Valignment set to Top and Halignment set to Right. Java Doc
GridPane.setHalignment(descriptionLabel, HPos.RIGHT);
GridPane.setValignment(descriptionLabel, VPos.TOP);
After looking at you picture again, I think you only need setValignment.

Related

JavaFX - Multiple nodes in one Grid Cell with specified width (in percentage possibly)

So I'm trying to add multiple Nodes in one Row of a GridPane with sizes in percentages. This is the UI, with the Grid Lines visible:
When the user clicks the Checkbox for "Check Editbuffer Checksum", I want to display a ComboBox next to Checkbox in the same Row and Colum. My problem is, that the Combobox fits the entire Cell, so the Checkbox is not visible anymore. Basically, it should look like this:
And if the user deselects the Checkbox the ComboBox should disappear again. This is the code to create the GridPane:
private void fill() {
getChildren().clear();
getRowConstraints().clear();
setMinWidth(350);
setPadding(new Insets(17));
setVgap(5);
setHgap(5);
lTitle.setAlignment(Pos.CENTER);
fxAssign.setMaxWidth(Double.MAX_VALUE);
RowConstraints heigthPadding = new RowConstraints();
heigthPadding.setPercentHeight(40);
add(lTitle, 0, 0, 2, 1);
getRowConstraints().add(heigthPadding);
addRow(1, lName, fxName);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
addRow(2, lRequest, fxRequest);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
addRow(3, lHeader, fxHeader);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
addRow(4, lLength, fxLength);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
addRow(5, lForm, fxForm);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
addRow(6, lCheck, fxCheck);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
add(fxAssign, 0, 7, 2, 1);
getRowConstraints().add(new RowConstraints(ROW_HEIGHT));
ColumnConstraints columnConstraints1 = new ColumnConstraints();
columnConstraints1.setPercentWidth(50);
ColumnConstraints columnConstraints2 = new ColumnConstraints();
columnConstraints2.setPercentWidth(50);
getColumnConstraints().add(columnConstraints1);
getColumnConstraints().add(columnConstraints2);
setGridLinesVisible(true);
}

QWidgets added to grid layout are placed as if it was a vertical layout

I am building an application that includes a scroll area that starts empty. Then, an unlimited number of different widgtes can be included at user request. As the widgets are not large, I would like them to be placed in a grid, organized in rows and columns. Ideally, the rows would be filled right to left, top to bottom.
I would like them to be placed like in the image below, where numbers indicate the order in which they are added:
However, what I get is this:
What I am doing is the following:
In the ui file I have a scroll area that includes a grid layout, with this setup:
In the code, I add the widgets. I am actually using my own widget classes but the procedure is the following:
QWidget *w1 = new QWidget(this);
ui->layout_output_grid->addWidget(w1);
QWidget *w2 = new QWidget(this);
ui->layout_output_grid->addWidget(w2);
QWidget *w3 = new QWidget(this);
ui->layout_output_grid->addWidget(w3);
QWidget *w4 = new QWidget(this);
ui->layout_output_grid->addWidget(w4);
QWidget *w5 = new QWidget(this);
ui->layout_output_grid->addWidget(w5);
Question
Is there any way to do this?
As a workaround, I assume I could keep count of the widgets added and implement rows as different horizontal layouts but I would like to know if there is a solution to get Qt to place the widgets the way I want?
You can specify which row, column and rowspan/columns the widget you want to add (1,2,3,4,5) must occupy.
Look for this overloaded function: https://doc.qt.io/archives/qt-4.8/qgridlayout.html#addWidget-2
In this case you should do something like this:
QWidget *w1 = new QWidget(this);
ui->layout_output_grid->addWidget(w1, 0, 0, 1, 1);
QWidget *w2 = new QWidget(this);
ui->layout_output_grid->addWidget(w2, 0, 1, 1, 2);
QWidget *w3 = new QWidget(this);
ui->layout_output_grid->addWidget(w3, 1, 0, 1, 1);
QWidget *w4 = new QWidget(this);
ui->layout_output_grid->addWidget(w4, 1, 1, 1, 1);
QWidget *w5 = new QWidget(this);
ui->layout_output_grid->addWidget(w5, 1, 2, 1, 1);

Get Pane size without adding it to a scene (in JavaFX)?

If I create a Pane (with nodes inside it), how can I compute the width/height without rendering it on-screen?
I am trying to create a document (in memory) and send it to a printer. The problem is that I need to compute how many pages and to do that I need to get the dimensions of the document.
A quick example I'm experimenting with:
Label testLabel1 = new Label("TEST1");
Label testLabel2 = new Label("TEST no. 2");
GridPane testGl = new GridPane();
testGl.add( testLabel1, 1, 1 );
testGl.add( testLabel2, 2, 2 );
VBox testVBox = new VBox( testGl );
Pane testPane = new Pane( testVBox );
//I read that this might be required
testPane.applyCss();
testPane.layout();
//Also that a delay is needed for the fx tread to update testPane
// (but shouldn't this all be in the same thread since it is in the same function?
// It doesn't seem to help).
Platform.runLater( ()->{
System.out.println( ">>> "+ testPane.getBoundsInLocal().getWidth() );
});
All I ever output is >>> 0.0. Note that in the program I'm developing, I have multiple Panes inside a "container" Pane. Hence, the variable testPane.
Thank you.
You need to add the Pane to a Scene for the layouting to work. There is no need to display the Scene however and there is no need to keep the Pane in this scene:
Label testLabel1 = new Label("TEST1");
Label testLabel2 = new Label("TEST no. 2");
GridPane testGl = new GridPane();
testGl.add(testLabel1, 1, 1);
testGl.add(testLabel2, 2, 2);
VBox testVBox = new VBox(testGl);
Pane testPane = new Pane(testVBox);
// add testPane to some scene before layouting
Scene testScene = new Scene(testPane);
testPane.applyCss();
testPane.layout();
System.out.println(">>> " + testPane.getBoundsInLocal().getWidth());
// Pane could be removed from scene
Group replacement = new Group();
testScene.setRoot(replacement);
Note that if you want to remove the root from a Scene you have to replace it with a non-null node.

Qt: what layout or combination of layout should use in this case?

I am working on a Qt Project and for this project I require to design something like this:
I have designed so far in Qt Creator and I have the component ready, but when I am trying to add widget in different layouts, I am not getting the shapes I want. What should I do to make my application resizable?
Catches:
Sidebar has fixed width, which means for horizontal increment of window size the sidebar's horizontal width won't increase. Sidebar itself is a widget.
upperbar's vertical width is fixed (if possible). Which means, during vertical window size increment the upperbar can't become vertically wider. And it itself is also a widget.
the widgets by the side of sidebar are in a qstackedwidget.
Nested layouts:
(green square = QStackedWidget)
Steps:
[Definition]
H(x, y, ...) = horizontal layouts on x, y, ...; where x, y, ... are widget(W#) or Layout(L#)
V(x, y, ...) = horizontal layouts on x, y, ...; where x, y, ... are widget(W#) or Layout(L#)
Step 1: V(W1, W2) = L1
Step 2: H(W3, L1) = L2
Step 3: V(W4, L2) = L3
Step 4: Set L3 as the layout of current page of the StackedWidget layout
Step 5: H(W5, StackedWidget) = L4
Step 6: H(W6, a spacer, W7) = L5
Step 7: V(L5, L4)
Notice that W6 and W7 are fixed in horizontal size (or set maximum on it), the spacer between them acts as the only resizable widget in the layout L5.
And here is the hierarchy:
Just for fun, the code version, with minimal optimized code...
#include "mainwindow.h"
#include <QBoxLayout>
#include <QLabel>
#include <QStackedWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Ingredients (taken from the mockup from top-left to bottom-right)
QFrame *upperBar = new QFrame;
QLabel *upperIcon = new QLabel("icon");
QLabel *profilePicture = new QLabel("profile picture");
QFrame *sideBar = new QFrame;
QLabel *sideItemA = new QLabel("Item A");
QLabel *sideItemB = new QLabel("Item B");
QStackedWidget *contentStack = new QStackedWidget;
QFrame *contentPage1 = new QFrame;
QLabel *page1WidgetA = new QLabel("I am widget A");
QLabel *page1WidgetB = new QLabel("I am widget B");
QLabel *page1WidgetC = new QLabel("I am widget C");
QLabel *page1WidgetD = new QLabel("I am widget D");
QWidget *centralWidget = new QWidget;
// The needed layouts:
QHBoxLayout *upperBarLayout = new QHBoxLayout;
QVBoxLayout *sideBarLayout = new QVBoxLayout;
QGridLayout *page1GridLayout = new QGridLayout;
QGridLayout *centralLayout = new QGridLayout;
// Let's connect the pieces:
/* First we setup the upperbar: */
upperBarLayout->addWidget(upperIcon, 1, Qt::AlignLeft);
upperBarLayout->addWidget(profilePicture, 3, Qt::AlignRight);
upperBar->setLayout(upperBarLayout);
upperBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
/* Then we setup the sidebar: */
sideBarLayout->addWidget(sideItemA);
sideBarLayout->addWidget(sideItemB);
sideBarLayout->addStretch();
sideBar->setLayout(sideBarLayout);
sideBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
/* Then we setup the content stacked widget */
page1GridLayout->addWidget(page1WidgetA, 0, 0, 3, 1);
page1GridLayout->addWidget(page1WidgetB, 0, 1, 1, 1);
page1GridLayout->addWidget(page1WidgetC, 1, 1, 2, 1);
page1GridLayout->addWidget(page1WidgetD, 3, 0, 1, 2);
contentPage1->setLayout(page1GridLayout);
contentStack->addWidget(contentPage1);
contentStack->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
/* Finally we setup the main elements into the central layout... */
centralLayout->addWidget(upperBar, 0, 0, 1, 2);
centralLayout->addWidget(sideBar, 1, 0, 1, 1);
centralLayout->addWidget(contentStack, 1, 1, 1, 1);
centralWidget->setLayout(centralLayout);
setCentralWidget(centralWidget);
/* Let's color it a little to better realize the positioning: */
setStyleSheet("QWidget {"
"border: 1px solid black;"
"color: red"
"}");
}
MainWindow::~MainWindow()
{
}
Here is the result:

JavaFX: Making BorderPane's Center's contents not strech

just a quick one for you since I'm generally inexperienced in designing apps. Any help would be greatly appreciated.
I've got the following application, and it's obvious that it uses a BorderPane for its layout. I've got a GridPane of 5 labels and 5 textFields in the Center region, and I wanted a subtle border for it.
As you can see, the GridPane utilizes the full space allocated to it in the Center region, and although the border gets drawn nicely, it goes all the way down to the bottom of the Center region (Red arrows).
What I want it to do is finish at the blue line.
I tried using grid.setPrefHeight(400);, for example, but it didn't work.
Are there any solutions other than the obvious one, to add a second container below the GridPane and squeeze the upper container enough?
EDIT: For reference, this is the code that creates the center area GridPane:
public GridPane addGridPaneCenter() {
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(0, 10, 0, 10));
sihuid = new Text("SIHU ID:");
sihuid.setFont(Font.font("Inconsolata", 16));
grid.add(sihuid, 0, 1); //spans from 0,1 to 1,1 (Column-Row)
sihuid_tf = new TextField();
sihuid_tf.setEditable(false);
grid.add(sihuid_tf, 1, 1);
mac = new Text("Plug MAC:");
mac.setFont(Font.font("Inconsolata", 16));
grid.add(mac, 0, 2);
mac_tf = new TextField();
mac_tf.setEditable(false);
grid.add(mac_tf, 1, 2);
loc = new Text("Location:");
loc.setFont(Font.font("Inconsolata", 16));
grid.add(loc, 0, 3);
loc_tf = new TextField();
loc_tf.setEditable(false);
grid.add(loc_tf, 1, 3);
appl = new Text("Appliance:");
appl.setFont(Font.font("Inconsolata", 16));
grid.add(appl, 0, 4);
appl_tf = new TextField();
appl_tf.setEditable(false);
grid.add(appl_tf, 1, 4);
type = new Text("Type:");
type.setFont(Font.font("Inconsolata", 16));
grid.add(type, 0, 5);
type_tf = new TextField();
type_tf.setEditable(false);
grid.add(type_tf, 1, 5);
grid.setPrefHeight(400);
grid.setStyle(
"-fx-border-color: #b8b8ba; -fx-border-width: 1;"
+ "-fx-border-radius: 4;"
/*+ "-fx-font: " + "Inconsolata" + ";" */
);
return grid;
}
After that, there's a simple
GridPane grid_center = addGridPaneCenter(); //CENTER Grid, contains info about plugs.
border_pane.setCenter(grid_center);
Scene scene = new Scene(border_pane, 900, 700);
scene.setFill(Color.GHOSTWHITE);
primaryStage.setTitle("PlugControl v0.1e");
primaryStage.setScene(scene);
primaryStage.show();
I'm afraid this is behaviour of BorderPane is by design (ref):
The top and bottom children will be resized to their preferred heights and extend the width of the borderpane. The left and right children will be resized to their preferred widths and extend the length between the top and bottom nodes. And the center node will be resized to fill the available space in the middle.
You should probably put the GridPane in an AnchorPane or VBox and put that (AnchorPane or VBox) in the center of the BorderPane.

Resources