I am wondering if anyone can help me with the generation of this layout:
I have wasted a lot of time.
What I want is:
1) The sizes of jButton1, jLabel1 and jLabel2 are the same as their original ones on resizing.
2) The sizes of jTextField1 and jTextField2 will automatically expand on resizing, but the total width of jTextField1+jLabel1 is the same as jTextField2+jLabel2.
3) The heights of JTree1 and JTree2 will automatically expand on resizing, and their widths are the same. They need to be placed in a JScrollPane so that there will be scrollbars when the trees get expanded.
Thanks a lot!
Look here:
http://download.oracle.com/javase/tutorial/uiswing/layout/visual.html
I would personally wrap the whole thing in a GridBagLayout for the flexibility it offers. Beyond that I often find it easier to put stuff inside GridLayouts or BoxLayouts and then put those in the GridBagLayout so that I don't have to deal with specific weights for every object.
It may take some experimentation.. I would start with a BorderLayout with "Top" and "Center"
"Top" only contains the button (You may need to find a container that makes it do what you want--you have to find something that presses it out to the right size). Center contains the rest.
In center you place something that divides evenly, I think a horizontal flow layout will do that. Might also use a splitter to drag the sizes if you want.
In each of the two sides of the flow layout (or whichever works). you add a BorderLayout with the label and text at the "top" and the "center" being left for the tree.
For the label and text field you might want to use ANOTHER BorderLayout and specify west for the button and center for the field.
Your components should then resize the way you want.
In summary, perhaps something like:
BorderLayout
top:
BorderLayout
bottom:
button (May need to be in another container to get the size right)
center:
Split pane or flow layout
left side (Same as right side):
BorderLayout
top:
BorderLayout
west:
label
center:
textbox
center:
JTree
Related
I'm using JXMultiSplitPane (from SwingX 1.6.2) to implement a three-pane horizontal interface. In the center pane is a JTabbedPane with two tabs: one with a JTextArea (in a JScrollPane, of course) used for entering Markdown code and the other a JEditorPane (again, in a scroll pane) for displaying a rendered HTML preview. When the user switches to the preview pane, the text in the editor is processed and displayed in the preview pane.
My problem is that if I enter text in the editor with long lines, and then switch to the preview, the center pane will expand. Sometimes it's just by a little bit, other times it'll take up more room than is actually on the screen. But if I move one of the resize handles manually, everything will snap back in place.
I've found only two ways to deal with this before it happens:
Manually resize one of the panes before entering any text.
Give the center pane a weight of 1 in the MultiSplitLayout model.
I can't use the second one since it will expand the center pane to take up almost the whole window by default.
Is there a way to fix this?
Update
After a little more testing, even technique (2) doesn't keep the size constant; switching between the two tabs changes the size of the center pane slightly.
I now believe that the problem is partly with the tabbed pane. The JTextArea and the JEditorPane do not have the same size and that JTabbedPane is resizing when I switch between them (since I'm resetting the JEditorPane text every time. This wouldn't be a problem except that JXMultiSplitPane will keep automatically resizing the center pane until the user forces a specific size by resizing manually.
So I should be able to fix the issue by making the size of the JTabbedPane fixed, but still able to be resized by the handle bars. Any tips on doing that?
The MultiSplitLayout is .. a LayoutManager, so you have to understand how it works (me too, not overly familiar with it myself :-)
The basic layout happens according to the component's prefSize, the weights are for distributing excess/missing space relative to the pref. By default, the dividers are "floating", that is they are positioned between the components as layouted by the basic mechanism. The moment a user touches a divider, dividers are "not-floating", comp sized to fit in-between the dividers. That's the reason for you not seeing the size-greed after moving the divider once. So one ways out is to
setup the JXMultiSplitPane as usual, add the components and realize the frame
fix the dividers after the manager has done its initial layout
String layout = "(ROW " +
"(LEAF name=selector weight=0.15)" +
"(LEAF name=center weight=0.7)" +
"(LEAF name=list weight=0.15)" +
")";
JXMultiSpitPane pane = new JXMulitSplitPane((MultiSplitLayout.parseModel(layout))
// add components and realize the frame
...
pane.getMultiSplitLayout().setFloatingDividers(false);
Alternatively, give more weight to the weights - force the layoutManager to use them for the layout itself (instead of only for the distribution of excess/missing space). A side-effect is that the prefSize of the comps might be set (by the layout, which is a no-no-never, but who's perfect ;-)
pane.getMulitSplitLayout().setLayoutByWeights(true);
Not sure which way I would prefer or if/how that could be made easier in the multisplit ..
How would I go about making the length of the tabs automatically resize based on how much room is left in that row of tabs.
Picture:
As you can see the tab's width is based off the text in the tab.
If you need me to explain what I want better then just ask me because I don't know if I made it clear enough.
You can use a custom component and set it's preferred size. For example, in ButtonTabComponent of TabComponentsDemo:
label.setPreferredSize(new Dimension(...));
You have to choose an appropriate dimension based on other aspects of your layout, so it won't be automatic.
I want to define a size for the actual tabbed pan.
The size of the JTabbedPane is a function of the dimensions and LayoutManager of the Container to which it has been added. In the example cited, the default layout of the frame's content pane is BorderLayout, and add(pane) adds it to the center by default.
To accomplish your goal, I see two approaches:
Divide the current width of the enclosing Container among the existing tabs and repaint the tabbed pane, as shown in this example.
Develop your own implementation of TabbedPaneUI and interpret SCROLL_TAB_LAYOUT accordingly.
I created a JFrame initialized with a BorderLayout and a JScrollPane as its CENTER element.
The scroll pane is set with VERTICAL_SCROLLBAR_ALWAYS and HORIZONTAL_SCROLLBAR_NEVER policies. The intent of my frame is to have a controlled width, while the height should grow/shrink as data is added/removed.
Inside my scroll pane, I added a simple JPanel (lets call it the content panel) which is initialized with a FlowLayout (and LEADING policy).
In order to test this, I simply populate my content panel with 20 JLabel("Item " + n) components where n is the loop counter.
I would expect to see my labels shown on a single row if the frame is large enough and the labels wrap to other lines when I shrink the width. But instead, there is only a single line displayed with no wrapping... ever.
Does anyone know why the flow layout does not wrap when a scroll pane is involved?
If I remove the scroll pane all together and put the content panel directly in the frame, the desired wrapping effect occurs, but if the frame height is shrunk smaller than the content panel height it just disappears.
The idea is that I want my labels to be wrapped when necessary but also always be visible if it means having to scroll up/down.
Any suggestions on how to fix this?
Thanks.
Wrap Layout gives an explanation and a solution.
If you work with the designer, you have to set the prefferedSize property to null (delete what is set) then set the preferred size by clicking the triple dots [...] button next to the prefferedsize property name and put your preferred value.
I encountered the same problem and it works for me.
In which Swing layout manager it is possible to change layout areas programmatically? And how to do this with lowest cost?
I have to create component with functionality similar to JSplitPane but with three panels from scratch. One of the moments is to Expand/Collapse one of the panels after clicking oneTouchExpandable button on the divider. But the problem is that I don't know how to implement this collapse action. I tried just setting panels width to 0, but the layout area which contains this panel doesn't shrink after the component. I tried to do this in all Layout Managers, but effect is the same.
Thanks.
When making a change that affects the layout of a panel after the GUI is visible you need to revalidate() the panel which essentially invoke the layout on the panel. In your case it might be easier to simply make the component invisible:
component.setVisible(false);
panel.revalidate();
panel.repaint(); // this is only required sometimes
All layout managers resize dynamically. However, the width and height properties are the result of the layouting, and will be overwritten.
The properties you should look at are preferredSize, minimumSize, and maximumSize - the layout managers base their calculations on those properties, though the exact effect depends on the layout manager (e.g. BorderLayout will give the NORTH, SOUTH, WEST and EAST components their preferred size if possibe and assign the remainder to the CENTER component).
Once you've changed the size properties, you have to call revalidate() on the container, then you should see the changes.
I'm with the revalidate()/preferredSize answers but just wanted to suggest this: don't re-invent the wheel! Use the JideSplitPane (part of JIDE's free "Common Layer") - it supports more than two splits.
Thanks to all for the answers. Finally I ended up with combining solutions from several answers.
My final solution is following:
I use BorderLayout, set West, Center and East panels and then manipulate their sizes by setting PreferredSize to West and East panels. The scheme of rendering is following: while laying out the components BorderLayout gives East and West panels their PreferredSize and rest of the space to Center panel. So with a bit of easy calculations I can manipulate size of each of three panels painlessly.
I also added dividers(originally just JPanel components with fixed size) to West and East panels(their size is also considered while calculating). For dynamic resize I handle dragging events on this dividers and recalculate panel sizes.
Refreshing is done with following snippet:
container.setVisible(false);
container.revalidate();
container.repaint();
container.setVisible(true);
I'd like to put this code somewhere to be available for others, but don't know where exactly to do this. So if you know such place, please point me to it in the comments.
I'm using a borderLayout to arrange my components in a JFrame and a Box(BoxLayout.X_AXIS) to put buttons next to each other. But it creates two problems:
I want the buttons to have the same size, but it automatically resizes them to fit the text within them (especially annoying when I change the text inside a button at runtime)
I want the buttons to have a little bit of space between them (let's say 10 px)
Is this possible using the borderLayout, or do I need to use the setLayout to null? And if so, wouldn't this screw up the original placement of the buttons in the frame? Or would this still be dealt with by the Box which is placed with the borderLayout?
A couple of suggestions
Try setting the preferredSize to a suitable Dimension value
If that doesn't work, try also setting the maximumSize and minimumSize to this same Dimension value
If that still doesn't work, change the buttons' layout manager to a GridBagLayout. The advantage of this layout manager is that it lets you control the layout's behaviour in minute detail. The disadvantage is that you usually need to configure a large number of properties on the GridBagLayout in order to get the desired behaviour. I'd advise checking out a GridBagLayout tutorial first, as it's a reasonably complex beast.
If you want them to have the same size then just add the buttons to a GridLayout and they will automatically be sized to the largest text string. You can also specify a gap between components.