Automatically expand JTree to until height threshold is met - java

I have a JTree on a JScrollPane as part of my GUI. I've set up an AncestorListener where I respond to the ancestorAdded event. In the event, I would like to automatically expand as many visible nodes as possible. By visible, I mean that I want to expand as many nodes as possible such that the total height of the tree does not exceed the maximum height of the JScrollPane's viewport. If my viewport had 500px of visible space, I want the tree expanded until the total expanded height is less than or equal to 500px.
I've tried to achieve this a few different ways. It boils down to this: I can't seem to retrieve an updated height for the tree after programatically expanding a node. How can I recalculate the height of the tree? tree.getHeight(), for example, always returns the same value even after I expand a node. Invoking tree.invalidate() between calculations didn't help either.

How can I recalculate the height of the tree?
Maybe getVisibleRowCount()*getRowHeight() will give you the correct size.
The documentation for getRowHeight() states that it may return <= 0 and leave the row height up to the renderer, which may be the case for you as you're using a JTreeTable.

Related

Calculating preferred height based on actual Codenameone's component width

I'm creating a custom Codenameone component that has variable size. The component displays a fixed amount of text, spanning multiple lines. Thus the width and height are related. If the width is small less text fits on a line and more lines are needed. I've managed to set preferred width and preferred height. The trouble is that when the actual painting occurs the width is apparently given by the graphics object graphics.getClipWidth() and doesn't match my preferred width. Thus my preferred height (which appears equal to graphics.getClipHeight() when painting) is incorrect as the clip width is unequal to my preferred width, which was used to calculate the preferred height. How can I get graphics.getClipHeight() to have the correct height? In other words, is it possible to specify the height of the component using the width the component will actually have when rendering?
Best wishes
Marc K
That's the exact problem we have with the TextArea and I'm afraid there are no easy answers. E.g. if the component provides a preferred size of X the layout manager might decide to allocate size differently thus requiring a different layout.
This was a conscious design choice we made when building Codename One, in order to accomplish this you will need to "reflow" effectively recursing thru the hierarchy recalculating sizes/dimensions until you get the best fit. These algorithms are by definition slow and harder to benchmark (since its hard to predict how reflow will behave on the device with varying fonts, paddings etc.).
In the TextArea we have a "poor mans reflow" that triggers revalidation if the width doesn't seem right. This has been a source of many problems in TextArea.
You can see this in the TextArea source, search for the setShouldCalcPreferredSize calls.

Java Swing - Dynamic List that Fills Available Space?

This doesn't seem like it should be very hard but I can't figure out how to do this:
I have a subclass of JPanel. It has a fixed height, but can be any width. The subclasses, on construction, set their preferred size using setPreferredSize(), which means I have to provide a width in addition to the height.
I would like to make a scrolling list of some number of my subclass, where the subclasses all fill the available horizontal space.
Right now I have a scroll view containing a JPanel containing my subclasses. The containing JPanel uses a BoxLayout with a vertical orientation.
Vertically, it looks great. Horizontally, my custom panels are just stuck at the preferred size. What would be the easiest way to make my panels fill the available horizontal space? I tried writing some layout listeners for them, but the performance was flakey (it seems that sometimes the event messages get dropped?) and the code looked hacky. Other views, such as the JList, JTree, and scroll views seem to resize automatically to fill the available space in a BoxLayout, so I feel like there must be something I can do in my JPanel subclass that I haven't thought of.
I'm open to using another Layout Manager if something else is better suited for this. I looked at GridBagLayout, but that seemed more geared towards static layouts where components aren't added and removed at runtime.
Edit: I found this on Oracle's Documentation for BoxLayout which has an example that looks exactly like what I want:
What if none of the components has a maximum width? In this case, if all the components have identical X alignment, then all components are made as wide as their container. If the X alignments are different, then any component with an X alignment of 0.0 (left) or 1.0 (right) will be smaller. All components with an intermediate X alignment (such as center) will be as wide as their container. Here are two examples:
Could someone show me the code that will produce the same results? The example code in the documentation doesn't look like it covers this particular picture.
When you put your component in a JScrollPane, your component may implement the Scrollable interface to adjust the scrollpane’s behaviour. By doing this you can implement the method getScrollableTracksViewportWidth() to return true so your component will always have the available width and be scrollable in vertical direction only.
This is how JList, JTable, JTree, and all the text components of Swing do it.
Alright - I found the problem. It appears that the default implementation of getMinimumSize() and getMaximumSize() will simply return the value of getPreferredSize() if it is set. So by setting a preferred size without a maximum size, my maximum size was the preferred size. By overriding getMaximumSize() to return (99999, preferredHeight), it now works exactly as I want.

Vaadin relative sizing with component proportions?

I have a GridLayout I'm making which is populated with a bunch of pictures. The GridLayout itself is set to SizeFull(), as is each individual image in the grid.
The grid with the pictures is within another grid, and that grid has relative sizes set.
With this set up, the grid of pictures stays within the spot I want it to, properly resizing to fit within the space they should, but the pictures do not retain their proper square proportions. They squish fat or skinny however they want. I want them to retain the original proportions, though, so they expand to fill their available area as much as possible while retaining those proportions.
If I set the width to 100%, or the height to 100%, and leave the other undefined, then it retains the proportions, and properly expands to fit the one that is set to 100%, but the other spills outside the nested grid layout's spot in the upper grid layout.
Anyone know how to do this?
Have you tried setting the width and height as percentage?
So on an image of 80 by 120 pixels:
setWidth(66, Unit.PERCENTAGE)
setHeight(100, Unit.PERCENTAGE)

Finding on-screen region in JavaFX

Seems like this should be easy and obvious but I can't find the answer anywhere. I'm using JavaFX 2 and I need to find the width and height of the region of a node that is currently being displayed on screen to the user (NOT the width and height of the node in the whole layout).
So if the window is scrolled so that my node is halfway off the edge to the right, I'd expect to get a displayed width of half the node's width and a displayed height equal to the full height. Should be easy; isn't. Anyone know how it can be done?
A half-acceptable solution for me would be to use the dimensions of the window itself. Is this the same as the width / height of the Stage?
Thanks
Isn't this a simple calculation using the viewport dimensions of the scrollpane and the coordinates/dimensions of your node?
It would be easierto help if you could post a simple testcase to experiment with.

Fixed percentage based grid with MiGLayout

I am trying to create a grid with MiGLayout that is enforced on its children. This means that if I insert a child into grid position (1,1) and the grid's size is [10%!] that this child must NOT be bigger and overlap other cells. The child must be shrunk to fit the Grid cell.
This is what I have so far:
new MigPane("", "[5%!][20%!][5%!][65%!][5%!]", "[45%!][50%!][5%!]");
Now, I insert a big component (a picture that I have no control over) in Grid 1,1, like this:
migPane.add(myImageView, "cell 1 1, width 100%!");
However, that does not seem to restrict the ImageView at all.
How do I tell MiGLayout that I want "myImageView" to be put in grid 1,1 and size it to fit? Is there a "fit" keyword? :)
Note that specifying anything with pixels/points/mm/cm/inches is NOT what I want. My app always runs full-screen and must scale seamlessly (it is not a traditional form app, it is a video system using JavaFX).
It looks like percentages are supported, according to the docs:
Overrides the default size of the component that is set by the UI
delegate or by the developer explicitly on the component. The size is
specified as a BoundSize. See the Common Argument Types section above
for an explanation. Note that expressions is supported and you can for
instance set the size for a component with "width pref+10px" to make
it 10 pixels larger than normal or "width max(100, 10%)" to make it
10% of the container's width, but a maximum of 100 pixels.
Maybe try something like: "width max(100%, 100%)".

Categories