Prevent child from expanding to fit available width - java

I have a styled javafx Node (here referred to as myLabel) which needs to be a certain size (determined by its contents). I'm placing it in a GridPane, and if the containing column of the pane is large enough, the node expands to fill the extra space, but I want it to maintain its original size.
GridPane pane = new GridPane();
GridPane.setHgrow(pane, Priority.ALWAYS);
ColumnConstraints col0 = new ColumnConstraints();
col0.setHalignment(HPos.LEFT);
col0.setPrefWidth(300);
pane.getColumnConstraints().add(col0);
pane.add(myLabel, 0, 0);
In the above case, myLabel takes up the entire 300px width it has available, but I only want it to use the space that it needs.
I've tried setting GridPane.setHgrow(myLabel, Priority.NEVER), but this isn't having the effect I'm expecting (that the label will no longer be allocated additional space). I don't want to use myLabel.setMaxSize(...,...), as this gets in the way of the label having dynamic size, and I don't want to set any arbitrary constraints on it.

It turns out the option I was looking for was not setHgrow(myLabel, Priority.NEVER), but setFillWidth(myLabel, false).
It looks like setHgrow affects the size of the area containing the node, optionally increasing the size if there is more space available, whereas setFillWidth affects the size of the contained node, optionally increasing its dimensions to fit the size of the area containing it.
Source

Set Min,Max and Pref Width to 'USE_COMPUTED_SIZE'.
myLabel.setMinWidth(USE_COMPUTED_SIZE);
myLabel.setMaxWidth(USE_COMPUTED_SIZE);
myLabel.setPrefWidth(USE_COMPUTED_SIZE);

Related

How do I resize labels, text fields, etc. in the IntelliJ Java Swing form?

So, for example, I created a text field.
Tried to resize it
But once I release the mouse, it gets back to its original size
So how do I do it? How do I resize elements? And yes, I tried to change the minimum size, maximum size, preferred size but it does not work either, nothing happens.
You can do setLayout(null) on the parent or setPreferredSize on the components, either of which will allow you to resize your Components. But the best answer is to set your Font size to a larger size (setFont(...)) which will cause them to become bigger (have larger values in getPreferredSize) automatically.
JTextField tf = ...;
tf.setFont(tf.getFont().deriveFont(tf.getFont().getSize() * 2));

How GridLayout computes Composite size

In an SWT application, I have a composite with a GridLayout that has two columns. The first contains labels, the second texts and checkboxes. I use TextLayouts for some of them and paint them manually (in a paint listener), so I have to manually compute their sizes. I set the computed sizes for the widgets with setSize() and set widthHint and heightHint in their respective GridDatas. GridData objects for the labels (1st column of the grid) are created with (SWT.RIGHT, SWT.CENTER, false, false) and for the widgets in the 2nd column with (SWT.FILL, SWT.CENTER, true, false). The computeSize() for the widgets returns the sizes I expect (eg. no more then 68 pixels of width for the 1st column and 128 for the 2nd).
But the computeSize() for the Composite returns a width that is much larger than I expect to see (or want), namely 253, while I expect 68 + 128 + 3 * 4 + 2 * 2 = 212 or something near to it.
The pack() on the Composite, acccordingly, makes it grow much wider than I want. I can force the required width of the Composite with the setSize(), but subsequent actions on the shell containing my composite invoke the composite's pack() anyway, so its width gets spoiled. Setting of the widthHint of the composite's GridData won't work either.
The Composite itself is a child of a upper-level Composite with GridLayout and has a GridData with (SWT.LEFT, SWT.FILL, false, true).
Why the computeSize() decides that the width of the Composite should be 253, if the widths of the widgets in the columns are computed to be 68 and 128 pixels wide and their widthHints are set correspondingly? How does it work? What does it take into account, besides the computed sizes of the child widgets? Where can I find a description of its algorithm (the source of the GridLayout's layout (Composite composite, boolean move, int x, int y, int width, int height, boolean flushCache), which actually computes the size, is rather complicated and difficult to understand) ?
How can I make the layout managers keep the required width of the Composite while changing layout of the parent Composites, including the Shell (on resizing, font changes etc)?
GridLayout is full of surprises. If you are not dogmatically stuck to it, I recommend switching to FormLayout. This is much more powerful and gives you much much more control over the final result of your UI. It is a paradigm shift compared to GridLayout, but it is very much worth learning it.
With FormLayout, you can use the dimensions of the parent, or the position and dimensions of any sibling Controls (ie. Controls sharing the parent) for positioning and sizing controls. It's like declaring a couple of layouting constraints per control and the manager will do its best to satisfy your wishes.
Here is a tutorial for you to get you started. It introduces you to FormData, which declares four anchor points (top, bottom, right, left) and the FormAttachments which define the constraints in a FormData object.
For your problem, you can layout the first column as using eg. 40% of the width of the parent, with each row being placed below the label of the previous row. The controls of the second column are placed relative to their label (on their left) and the label or control of the previous row (on their top).
Now what seems to bother you is the width of some of the controls in the second column. In FormLayout, you can set an explicite constraint for the right anchor, either by declaring it to be eg. at 100% width of the parent (starting from the 40% right anchor of the first column) which will then rely on the layout of the parent's parent, or by setting the right anchor as an absolute margin in pixels counting from the right edge of the first column. This can be done by referencing the label in the first column, but switching the alignment. This is necessary because by default, a relation from the right anchor of Control A to a sibling B will automatically use the left side of B. In code, this second possibility will spell out like that:
FormData fd;
//row 1
Label lblC1R1;
Control ctrlC2R1;
//row 2
Label lblC1R2;
Control ctrlC2R2;
...
fd = new FormData(); //for ctrlC2R2;
fd.top = new FormAttachment(lblC1R1); //top edge clings to (y-coord of) bottom of row 1 label (could reference row 1 control, too)
fd.left = new FormAttachment(lblC1R2); //left edge clings to right side of row 2 label
fd.right = new FormAttachment(lblC1R2, 200, SWT.RIGHT); //right edge is defined as a distance of +200 px from *right* side of row 2 label (by default, it would use the left side)
//we don't set fd.bottom, so the control may grow or shrink with ie. font size
ctrlC2R2.setLayoutData(fd);
This will fix the width of the second column control to 200px starting from the right side of the first column, no matter what the control says about its preferred size.

Change growth ratios for panes inside SplitPane

Have an horizontal split pane. If the pane grows, then the two interior panes will grow equally (if the split pane grows 100 pixels then each interior pane grows 50 pixels).
Is it possible to adjust this so that the second interior pane grows more than the first one? Like the first one gets 25% of the growth and the second gets 75%.
The SplitPane has no direct API for this, but indirectly we may achieve this..
The API doc gives us a hint:
The dividers in a SplitPane have the following behavior: [...]
Dividers moving to the left/top will stop when the node's min size is reached.
Dividers moving to the right/bottom will stop when the node's max size is reached.
[...]
So, by setting a minimum size, we can force the SplitPane to distribute the available space as we need it.
This is a little example with two TableViews aligned left and right in a SplitPane. Now I bound the minimum size of the left TableView to 20% of the Stages current width and the right ones to 70%.
TableView<?> table1 = createTable();
TableView<?> table2 = createTable();
table1.minWidthProperty().bind(primaryStage.widthProperty().multiply(0.2));
table2.minWidthProperty().bind(primaryStage.widthProperty().multiply(0.7));
SplitPane split = new SplitPane(table1,table2);
You can easily modify the minimum size, to constant values or bind them to different parent container sizes.

max size of JLabels being overridden by text width?

I have a JTable in which one column represents the size occupied by a folder on disk. Each row represents one folder, and this column has a list of rectangles; the width of each rectangle represents a percentage of the size occupied by one type of file. Here's a picture:
I do this by creating a JLabel for each file type in a row, then, in the getTableCellRenderer() method, I have an array of JLabels, one per file type. That method sets the preferred and maximum sizes of the JLabel to be the column height and the percentage of the column width for each label.
My problem comes when the picture is narrowed; the following was made by narrowing the frame of the program illustrated above:
As you can see, the percentage representation is gone, and the width of the JLabels now appear based on the width of the text, not on the preferred/max sizes set. If I narrow the window further, the percentage calculations again appear to take precedence; it is only in a narrow width range that I see this behavior.
Is there another way to do this? Do I have to draw rectangles and use drawText() instead of using the FlowLayout and text elision that already exists?
Here's the code that sets the characteristics of the JLabels:
sizeBlockDimensions[i].setSize(newWidth, rowHeight);
sizeBlockLabels[i].setPreferredSize(sizeBlockDimensions[i]);
sizeBlockLabels[i].setMaximumSize(sizeBlockDimensions[i]);
sizeBlockLabels[i].setBackground(color);
sizeBlockLabels[i].setText(labelText);
sizeBlockLabels[i].setVisible(true);
i++;
instead of using the FlowLayout
You should be able to use the Relative Layout. It was specifically designed for relative sizes and should adjust automatically as the space available changes.

How to ensure that text is rendered to fit in tree?

JTree does not seem to automatically resize its nodes to accommodate fonts of size 20+. I've tried calling revalidate(), but that doesn't seem to help. The text in the nodes appears "squished" vertically so that the top and bottom of letters are clipped.
How can I use large fonts and ensure that they are displayed properly with a JTree?
Some LAFs (e.g. WindowsLookAndFeel) set a fixed rowHeight which is rather arbitrary (like 16px). Be sure either to force the tree to dynamically compute the height for each node:
tree.setRowHeight(-1);
or calculate the rowHeight based on the tree's font and set that as the fixed height.

Categories

Resources