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.
Related
I am using a SplitPane control to divide all available space between two text areas allowing users to adjust split position according to their needs.
- SplitPane
- AnchorPane
- TextArea [1]
- AnchorPane
- TextArea [2]
Unfortunatelly textareas only take constant amount space (as was defined in SceneBuilder) and refuse to shrink to fill whole area of SplitPane's AnchorPane:
How to get it fixed up?
I'd suggeset to put the AnchorPanes in a GridPane so you can set percentages for the vertical metrics for example (don't remember if this also works with split pane),
and then bind the properties
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);
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.
I have a layout where I have a vertical split pane that divides two components. The component inside the right side of the splitpane I want to grow (it's an image), but the components on the left side of the split pane I want to remain in the exact same place with the divider in the exact same position when the window is enlarged.
I have attempted to wrap the left side AnchorPane in a Vbox and it seemed to work except when the window is resized all of the components in the left side get moved down. This also occurs when I wrap it in an HBox.
I can't think of the best way to fix this. I'm using scene builder and I'm still fairly new to Javafx. Can anyone help?
Thank you!
Calling setMinWidth and setMaxWidth on the component that must not grow with the same fixed value will prevent the user to change the divider position.
So for example let's say that you want a max size of 100 for your left component, the code could be:
SplitPane pane = new SplitPane();
double leftComponentSize = 100.0;
VBox leftComponent = new VBox();
// Set the min and max width to a fixed size
leftComponent.setMinWidth(leftComponentSize);
leftComponent.setMaxWidth(leftComponentSize);
...
pane.getItems().addAll(leftComponent, rightComponent);
// Initialize the divider positions to allocate the expected size
// to the left component according to the size of the window
pane.setDividerPositions(leftComponentSize / stage.getScene().getWidth());
I have a horizontal scrollbar that controls a large panel (with a very large width, and a very small height, thus an horizontal panel).
I want the start of the scrollbar (when the knob is at max left) NOT to start at the beggining of the panel it is scrolling, but rather in a specific place that I dictate. The same for the end of the scrollbar (when the knob is at max right).
I find that the scrollbar is always bound to the panel it is scrolling, and I can't figure out how to change its behaviour.
EDIT:
As an example, picture a normal web-page: when at the top of the page, the scrollbar knob is also at the top. When at the bottom, the scrollbar knob is at the bottom. I want to define new limits for the content, such that when the scrollbar knob reaches the top or bottom, the page is showing the limit I defined, instead of the real top and bottom.
As shown in How to Use Scroll Panes, you can use the component's scrollRectToVisible() method to scroll to an arbitrary Rectangle. There's an example here.
Addendum: As a Container, a JPanel is fairly fungible even if it has considerable nested content. One reliable way to swap content at a given level is via CardLayout, shown here, here and here.
I solved the problem by using the JScrollbar method setValues(), which allows me to set at the same time the maximum, minimum, value and extent of the scrollbar. By setting the maximum and minimum to the values I want, the scrollbar behaves as I wanted/expected.
The problem was that I was only setting maximum and minimum values (setMaximum, setMinimum), and since there is a strict policy at the model that minimum <= value <= value+extent <= maximum, that estrategy did not work.
Would it be possible to keep the large panel as a backing store and copy the region of interest into a panel which is actually realized in the scrollpane. This way you don't have to fight the behavior of the scrollpane.