my dog learned polymorphism*
The moose likes Swing / AWT / SWT and the fly likes Trying to understand how layouts resize Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Android Security Essentials Live Lessons this week in the Android forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "Trying to understand how layouts resize" Watch "Trying to understand how layouts resize" New topic
Author

Trying to understand how layouts resize

Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
I have not had much luck getting a GUI put together where the components are sized correctly in their respective windows. Here is one example. I tried to simplify things by making the right and left panels just a panel with a preferred size.

I tried to get a 60:40 split. When the GUI comes up, it looks about right. If I just grab one side and make it bigger, it seems to grow appropriately. If I shrink it, the right panel becomes very very small compared to the left panel and disappears when the left panel is still 8 cm wide. If I just increase and decrease the width of the GUI, the relative sizes of the two panels change and I can have anything from the two panels being the same size to the right panel being bigger than the left panel. That's without touching the divider, just resizing the whole window.
I seem to be able to get the right panel much bigger than the left panel just by shrinking the GUI height and width down to nothing and back up again.

Is there a way to get better behavior from the split pane? I'm not sure if some of the problem is with setting a preferred size, but in the 'real' code I have objects that have sizes and I am having difficulty getting a panel that I want to be small, but has a lot of objects in it to be small compared with another panel that I want to be large, but has just a few objects. The size hints didn't seem to be helping much. Java seemed to be making up its own mind about relative weights. I will post other examples later where I wanted three vertically stacked panels of equal size and when I re-size, the bottom two disappear, somewhat like with the left and right frames here. Or if I have a 'busy' right frame (lots of objects) it gets most of the width with the split pane, no matter what preferred size I request for the panes.

I'm not sure what I good balance of providing a simple example versus providing more code to show my exact problem. So if I need to be more detailed, let me know.







Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2156
    
    7
I'm not sure what I good balance of providing a simple example versus providing more code to show my exact problem.


We generally ask that you post an SSCCE to demonstrate the problem. Basically this means the minimum amount of code to show the probloem. In you case it looks like gave minimum code but you didn't give it in the proper format. I don't want to copy 4 files to my machine. Generally a SSCCE is a single file that we can copy, paste, compile and execute. There is no need for you to extend a component simply to set the properties of the component.

Instead the code should be something like:



The split pane resize usually works fine for me. However you need to be aware that split pane respects the minimum size of a panel. So depending on the compnents you add to the panel you can only shrink a panel to its minimum size. I don't think this will be an issue with your posted code since you didn't add any components to the panel. However, in your real application is may be the problem.
Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

JSplitPane has a method 'setResizeWeight' which takes in a double parameter - 0.5 provides equal weightage - I would see this corresponding to percentage and I think this is the method you need to set to achieve the balance. A value of 0.6 would correspond to 60:40 in your case.

API quote:
public void setResizeWeight(double value)

Specifies how to distribute extra space when the size of the split pane changes. A value of 0, the default, indicates the right/bottom component gets all the extra space (the left/top component acts fixed), where as a value of 1 specifies the left/top component gets all the extra space (the right/bottom component acts fixed). Specifically, the left/top component gets (weight * diff) extra space and the right/bottom component gets (1 - weight) * diff extra space.


Ranga.
SCJP 1.4, OCMJEA/SCEA 5.0.
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Ranga,

I thought the same, thing, but I am setting ResizeWeight (line 34 in the code that creates the splitPane or line 84 of code below). It comes up looking OK (though not 60:40 exactly). But I know that one thing that is going to be done with my code is someone is going to grab a corner of the window and change the size repeatedly to verify that the behavior is well-defined. And I found even with setResizeWeight, if you randomly resize the window, the sizes of the two windows don't retain their relative widths. The simplest way to see this is shrink the vertical height to 0, then shrink the horizontal width to 0 (or as close as it will go in each case). Then expand the width to full screen without expanding the height, then expand the height. I end up with a right panel much bigger than the left panel. I'm wondering if that is the best Java can do with standard Layout managers. I want to add to this though, as I can't even seem to get a 60:40 split depending on what I put in each panel. I've been using getPreferredSize() as the last line when I make a panel to see if they are bigger than would fit in the frame, they don't seem to be. I'll try to illustrate that Wednesday.

Rob,

This wasn't exactly the problem I was going to present, I also see that the starting widths seem to depend a lot on what is in the panels. So I was going to load new classes just for right and left panels to illustrate this. I also found if I stack three panels vertically within one gridbaglayout and change the height, I can get some pretty bizarre behavior. For example, the top panel becomes larger when the the height is reduced! Still working on trying to come up with a simple illustration of that one. Again, I thought I could do that by updating just one of my classes.

But if you would rather have one code block, here it is-

Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

Instead of the setDividerLocation(int), use the setDividerLocation(double). And, when I apply the hack mentioned in stackoverflow, it works very well for me (override paintComponent instead of paint as mentioned in the link).
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Thanks again Ranga.

I tried to implement your suggestions. I still find that a bit of random resizing will produce the situation where the right panel is considerably larger than the left. It takes a little more work, but basically resizing the window to nothing or almost nothing and then expanding it causes problems. I can make the left panel disappear completely. Shrink the window horizontally as much as you can, then shrink it vertically, then expand it horizontally as wide as you can, then expand it horizontally. This is on Windows 7 Java 1.6. I don't think it is worth more time. But just to be sure I understood you, the code I used is below.

I seemed to have needed the GridLayout for the JPanel, as with the default layout, the splitPane had no size.

I next want to see if I am going to focus on trying to demonstrate the problem I have when panels are stacked horizontally in a GridBagLayout. So I am hoping to get your advice on that when I get an example constructed. I think some of the problem is that one component is simply too big.

One thing I find odd is that in my actual application, if I set:



the left side is 10 cm and the right side is 9 cm.

Changing this to:


the left side is 9 cm and the right side is 10 cm (they reverse).

I did a getPreferredSize on each JPanel after a constructed it. There are two in the left split pane 505x176 and 500x350, respectively and three in the right split pane 340x234, 305x208 and 255x136, respectively. The 340x234 panel seems to be my problem, since 340 pixels on my screen is 8.6 cm. So I don't fault Java for getting a bit funky when there is not enough space. Likewise, 234 pixels is 6 cm. When the GUI comes up, the 340x234 panel is 5.4 cm high. When I reduce the WIDTH, at some point it's HEIGHT suddenly pops up to 7.3 cm. Sadly, if I just adjust the window until I get that panel to look best from a visual perspective, it is 8.2 cm x 4.8 cm or about 325x188 pixels. I can get Java to report a smaller preferred size by setting preferred size on the panels that make up the 340x234 panel (I have it at 330x209 at the moment) but it still pops to a much larger height when I make the width smaller. Ranga, this is the dialog you helped me with with labels inside panels in a GridBagLayout. It's very beautiful, but I think Java might be providing some padding that is making the dialog taller than it needs to be. As I said, I am trying to simplify the code and still illustrate the problem.


Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2156
    
    7
I am trying to simplify the code and still illustrate the problem.


No the code is not simplified. The code does not compile, it doesn't have a main() method. As I suggested earlier, there is no need to use RightPanel/LeftPanel classes that extend JPanel in a SSCCE. The panels can be built inline with code like I provided earlier, you simply create the panel and set the properties. I'm not about to go back to old examples to copy/paste portions of the code just to get it to compile.



This will not work. The size of the split pane at the time this statement is executed is 0. This method can only be used after the components have been realized, which basically means the frame has been packed or made visible.

Or you can use code like the following:


Of course this code assumes that your main() method also invokes the code to create the GUI on the Event Dispatch Thread.

You should not be overriding the paintComponent() method. You should NOT be setting the property of the component in that method. That method is for painting only.
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Rob, you didn't respond when I posted a compilable example. The latest code snippet was for Ranga, since he's given me a number of good ideas for resolving GUI problems I have been having. Follow his link and that is where you will find the suggestion for overriding the paint component.

Having looked at many more complaints about setDividerLocation, I am unclear on why the original approach of setting the initial divider position using a fixed integer value and then relying on setResizeWeight to handle resizing the window isn't 'what Java intended.' The only problem I see is that if I don't want the right window to grow much, I might assign a high resize weight and then when I return the main window to the original size, I've not returned to the original divider location. But, if the resize weight and divider location would produce different results then presumably rather than using resize weight I'd need to listen for window resizing and set the divider location manually at that time (or every time the SplitPanel repaints, not just the first time). Of course, there is the other problem that you can get the SplitPane to get the resizing completely wrong just by randomly resizing the window, I'm beginning to think that is just a bug which might be worked around by setting minimum sizes for the split panes.

So I think that gets me back to worrying over having Java have a proper understanding of the desired size of my components, since it is the extra space that is presumably parceled out by the resize weight.
Rob Camick
Ranch Hand

Joined: Jun 13, 2009
Posts: 2156
    
    7
Rob, you didn't respond when I posted a compilable example.


I'm not going to read over 100 lines of code when only 20-30 are required for a proper SSCCE. Extending JPanels is completely unnecessary for the SSCCE. How do you know that creating these extended classes isn't causing the problem??? Its unlikely they do, but the point of a SSCCE is to keep the code extremely simple because until you solve the problem you don't know what may or may not be causing the problem.

Follow his link and that is where you will find the suggestion for overriding the paint component.


As his comment alreadys says "its a hack" and a bad hack at that. As I already stated painted methods are for painting, NOT setting properties of a component.

Not only that, I stated what the actual problem was and gave 2 proper solutions.

You can learn to use Swing the way it was intended to be used or you can use hacks, in which case I'm outta here.

I can't comment on any of your other concerns because you haven't posted an SSCCE with any of my suggestion implemented.
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Here is an example of the behavior I get resizing one of my components. Here I just used two of the same components. I actually have three different types of components and as a result the behavior is a bit different from what occurs here. If you bring up the GUI initially, the two components are 104x124. If you shrink the width of the GUI, at one point the components suddenly become taller. I see the same problem with the larger GUI using scroll panes. If you shrink the height, the boxes become wider and they are no longer the same size. This is not exactly what I see in the complete GUI, in that case the lower component becomes smaller and the upper one suddenly becomes taller as you shrink the vertical height.

Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

Jon Swanson wrote:Here is an example of the behavior I get resizing one of my components.


Jon,
Lets stick to one issue per thread...we have been discussing splitpane here, so starting to look at another issue in the same thread makes it hard to follow. Please create a separate thread for this issue...
and if possible, change the subject of this thread to 'jsplitpane issue' or whatever.
Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

I am able to reproduce the problem...
this is the first time I am working on this problem, so, I just followed the hack which seemed to work...I apologize if I misled readers with that.

As per Rob, if the right way is to use SwingUtilities, then lets follow that. Basically, the setDividerLocation has to be called after the panel is made visible(painted), so I have put the invokeLater after setVisible(true) in my code.
I also, removed all the derived classes (including that for splitpane) and made direct calls. The problem still exists. I will try and see why it is so and if there is a solution available.

Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Ranga,

I posted another question about my problems with components getting bigger when I shrink the size of the window. That is probably a more pressing problem. I am feeling that for this problem, I should try to get the 'natural' size of the components I am creating to be a bit smaller, then experiment with resizeWeight until I get the two sides of the split pain to look about right when resizing. Then set an int divider location to correspond to what the combination of component size and resizeWeight would produce (hopefully close to the 60:40 I want). Finally, set a minimumSize on the panels so that they cannot be shrunk down to nothing, since that seems to be when the worst problems start happening.

I am still a bit confused on how Java apportions space, as when I do a 'getPreferredSize()' after creating the left component it reports a width of ~500, whereas for the right component it report ~300 for the width. So I'd have thought the left panel would get about 60% of the width. If I don't try to set anything, it gets less than half. The left panel is much simpler, just a table. The right panel is a series of nested panels each with its own GridBagLayout or GridLayout and all sorts of widgets inside. To me Java acts like it is giving more weight to a panel based on complexity. I also notice that an empty panel with e preferred size that is really large seems to get no respect when it comes to actually allocating space. The panel with real widgets gets most of the space.

I didn't see a way to change the title of this posting.
Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

Adding the following listener works for me in all cases:
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
Thanks,

If I am setting the divider location in this manner, it seems like there is no longer a need to set the resize weight, since whatever Java tries to do with it, I am just changing it by explicitly setting the divider location. Does that sound right?
Jon Swanson
Ranch Hand

Joined: Oct 10, 2011
Posts: 193
I stopped setting the resize weight and the split pane behaves beautifully with just the divider location set.

Thanks again Ranga, that was a very elegant solution.
Ranganathan Kaliyur Mannar
Bartender

Joined: Oct 16, 2003
Posts: 1076
    
  10

Yah, sure. Welcome.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: Trying to understand how layouts resize
 
Similar Threads
Drawing Problems with JPanel /Jframe need optimize solution.
add component to a visible component
Having problems making a simple GUI
Am I understanding observers/observables correctly?
form design