I have a TabLayoutPanel and i don't want to give it a fixed height like in the following code example (tabPanel.setHeight("100px");). I want to give it the height of the tab content e.g. the HTML-Widget in the first tab). If i don't set the hight manually, the tab content is not shown at all. Is there any way to get this working with a height adapted to the content?
public class GWTTest implements EntryPoint {
public void onModuleLoad() {
TabLayoutPanel tabPanel = new TabLayoutPanel(3, Unit.EM);
tabPanel.setAnimationDuration(400);
tabPanel.add(new HTML("Tab1 Content"), "Tab 1");
tabPanel.add(new HTML("Tab2 Content"), "Tab 2");
tabPanel.setHeight("100px");
RootPanel.get().add(tabPanel);
}
}
I also tried to mess around directly in the css with the "overflow" and "postition"-attributes, but this then breaks always the animation or something else.
Edit: It seems the easiest way would be to implement my own tab panel - or use an existing javascript library.
Layout panels are a special kind of container in GWT that required sizes from their parents and can size themselves. The basis is the two interfaces ProvidesResize and RequiresResize - indicates that the object will size its children, the other that it must be sized when the parent's size changes. Most layout panels (like TabLayoutPanel) implements both - it needs a size change from its parent, and when it gets it, it will size its children, each tab.
To kick it off though, you need to add the root widget to a RootLayoutPanel, not a RootPanel. There are several chief differences - there is only one RootLayoutPanel (no get(String) method), and the RootLayoutPanel will size its children, while RootPanel will not.
Use RootLayoutPanel.get().add(tabPanel) instead of RootPanel.get().add(tabPanel).
I have also ran up with this issue, but sadly it requires height to be set. All the workaround s where a failure. But some of them suggest the following.
You can try to replace the TabLayoutPanel with a HeaderPanel:
A panel that includes a header (top), footer (bottom), and content
(middle) area. The header and footer areas resize naturally. The
content area is allocated all of the remaining space between the
header and footer area.
Alternatively you can override the onResize() method your ResizeLayoutPanel calculate the height of your embedded content and set the appropriate height.
If you want scrolling functionality you have to embed your VerticalPanel in a ScrollPanel or use CSS to set the oferflow property.
Related
I'm trying very hard to understand GWT's layout system that they introduced in 2.0. It's supposedly recommended, but it seems much more complex that the old way.
What I want to do, (which I feel is a very basic design) is build an application with a header, left vertical menu, footer, and a scrolling content section.
So, to do that, you do this:
DockLayoutPanel panel = new DockLayoutPanel();
FlowPanel header = new FlowPanel();
FlowPanel menu = new FlowPanel();
FlowPanel footer = new FlowPanel();
ScrollPanel content = new ScrollPanel();
panel.addNorth(header);
panel.addWest(menu);
panel.addSouth(footer);
panel.add(content);
RootLayoutPanel.get().add(panel);
That works perfectly fine. Except, the ScrollPanel (where all content goes) apparently breaks the layout flow. So, in my activity, I have:
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus)
{
FlowPanel viewPanel = new FlowPanel();
panel.add(viewPanel);
}
If I add a TabLayoutPanel to the viewPanel, it will not display correctly. I have to add it to a LayoutPanel that is attached to a LayoutPanel that is attached to a LayoutPanel, etc. all the way up to the RootLayoutPanel.
So, I try this:
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus)
{
LayouPanel viewPanel = new LayoutPanel();
panel.add(viewPanel);
}
And in my ui:binder, I have:
<g:LayoutPanel>
<g:layer>
<g:TabLayoutPanel barHeight="3.33" barUnit="EM" height="500px">
<!-- tabs go here -->
</g:TabLayoutPanel>
</g:layer>
</g:LayoutPanel>
So 2 things here.
I don't want to set the height. I want the tab panel to be as big as the content. I don't get why you have to set heights in this "better" method of laying out your app.
It still doesn't show on the screen at all. I'm assuming because it's being attached to the ScrollPanel. What confuses me is that ScrollPanel does indeed implement RequiresSize and ProvidesResize, so is it not a valid LayoutPanel? That's literally all LayoutPanel does. It's a ComplexPanel that implements those interfaces
When I inspect the page, and hover over where the TabLayoutPanel should be, I get a blue highlight (in Chrome) as if it were there, but it seems the
<g:layer>
that wraps it has no height, so it hides the TabLayoutPanel. In fact, if I edit it in the viewer to have a height, the TabLayoutPanel does show.
Am I doing something fundamentally wrong here? I would very much like to do:
RootLayoutPanel > DockLayoutPanel > ScrollPanel > *Some Container > TabLayoutPanel
And for things to just... work. I'm trying to convert my current app to this new layout stuff to get rid of all the tables that get generated under the hood, but it seems to cause more problems than it fixes.
*This container has things above and below the Tab Panel
ScrollPanel in your proposed layout will occupy space given to it by DockLayoutPanel. If "Some Container" is never larger than space allocated to ScrollPanel, ScrollPanel will never scroll. If "Some Container" may become larger (i.e. the need for scrolling), then this container cannot get its size from ScrollPanel - its height should either be set explicitly, or it should be a regular FlowPanel which grows with its content. In both of these cases, this "Some Container" will not be able to provide any size to its children, including TabLayoutPanel.
It's hard to give advice without seeing the requirements, but if you need to include a TabLayoutPanel inside a panel that grows with its own content, you must set its height yourself - in code or CSS.
I have following situation: VerticalLayout with Labels inside it. (this layout is interrior of popup)
When I'm building the application I don't know lengths of the labels - the label contents are queried from database.
Is there any way to tell this VerticalLayout to have width enough to fit all labels without breaking them, but not bigger? I don't want labels to break, but I also don't want to have empty space in the popup.
By default, Vaadin labels have a width of 100%. You'll want to change that to "undefined", and the same for the VerticalLayout : In both cases setWidth(null) or setWidth(-1, UNIT_PIXELS)
I have a swing project and noticed that the elements inside the JFrame is statically located inside the JFrame and I do not have the option of resizing the elements as I want to.
My gui app inside the designer window looks like the following:
I want to resize the button (E.g.) by dragging the corners of the button, but I am not allowed to?
As you can see on the following picture, the dragging is not allowed per pixel, but only per section in the JFrame:
How can I disable the static placement of the elements/Enable the self-dragging of elements inside the designer window?
Most likely you will need to disable the LayoutManager. On Netbeans, Setting this to null would provide you full control over the location and dimension of the child elements, so I am assuming that something similar should work here (although you seem to be using Eclipse, if that is the case, please state what plugin you are using).
It is to be noticed however that usually you want to have a layout manager taking care of how your components are rendered. I would recommend you take a look here for some more information on layout managers prior to removing them completely.
Setting size and position of components in a GUI should be left to the JRE at run-time, using:
The preferred size of the component (with current content, in the current PLAF).
The borders/padding/insets set to the component.
The layout used.
The component spacing defined in the layout constructors.
The layout constraints used when adding components to the layout (especially important to e.g. BorderLayout and the much maligned GridBagLayout, as well as many 3rd party layouts).
Generally, complex effects are created by using a nested layout.
I am using a JPanel (with several labels inside) to add a dynamic information on a graph. This panel is dynamically created, it is not visible before I use it to draw.
For this, I am using a BufferedImage, and I follow approximately the same steps as described on this other question. It works good, as long as I specify all sizes (the panel, and its components).
Like asked as well in comments of the referred question, how can I determine the optimal size of this panel? The same operation would be done if this panel was displayed in a regular frame/layout setting.
In my case, how can I "pack", in a way, this panel, so that its size, and size of its content are set to the optimal (determined by the size of labels, then)?
Suraj and willcodejavaforfood put me on the good track.
Checking what is actually done in a pack() method, I see that this is mostly setting the current size to the one returned by getPreferredSize().
From this, I managed to make such solution:
// Creating the panel
JPanel lPanel = new JPanel();
//lPanel.setSize(1000, 1000); //default size, not needed anymore
lPanel.setLayout(new BoxLayout(lPanel, BoxLayout.PAGE_AXIS));
//Adding the content
lPanel.add(new JLabel("Blah"));
// etc...
//Adjust the panel to its preferred size
lPanel.setSize(lPanel.getPreferredSize());
//Call the layout method
//(this will adjust the content components to their correct size and position)
lPanel.doLayout();
This method works correctly, and adjusts the panel and its content to the correct size (and answers my question in a simplistic way: "how to find the preferred size? getPreferredSize()").
However, it requires to set the initial size to a large enough size, so that the content fits in, or they won't be put on the layout. This is a bit pity, and not really "clean", but I can't find a way to avoid that, for now.
Edit: Actually, the default size was not necessary, because getPreferredSize() returns the correct value, even before calling doLayout(). As such, the panel can be set to its proper size before calling the layout method.
The direct answer is to call Window#pack(). This method will automatically set the size of all underlying children to thier preferred sizes(ofcourse this depends on layouts of child containers, for e.g. BorderLayout doesent give a damn about preffered sizes).
So as long as you have set preferred sizes(or min/max sizes in case layouts are like BorderLayout) of your child components, pack() method will be all you need.
[UPDATE]One way is to do is add a HierarchyListener to your jpanel and check for HierarchyEvent#DISPLAYABILITY_CHANGED events. This event is called when your panel is realized that is ready to be shown(and a parent is available), at this moment you can do:
SwingUtilities#getWindowAncestor(myPanel).pack();
I have to build a rather large form with many controls. The controls are divided in basic controls/settings and extended controls/settings. The user can decide if he wants to see only the basic or both basic and extended controls.
I've dropped all extended controls onto their own JPanel so that I can easily switch between the two views by showing or hiding this panel.
Currently I'm using GroupLayout and what happens is that the controls on different panels are not aligned:
Label aaa: Text field
Label a: Text field
Label aaaaaa: Text field
----------------------------
Label b: Text field
Label bbb: Text field
Label bb: Text field
Unfortunatly I found now way to "synchronize" the layouts of the two panels (except using AbsoluteLayout and fixed control coordinates)
Is there any way to achive this?
Is my whole design flawed?
EDIT: If it is possible I would like to keep the GroupLayout manager.
As far as I know, no Swing LayoutManager (from JRE or open source) can span several panels.
I am currently working on such a feature (which I called "layouts synchronization") for my DesignGridLayout project, but it is not something easy to implements (I have started about 2 weeks ago and I still don't see exactly if and when I will get to something interesting, but I still have high hope for it;-))
One option you could check would be to add all components to the same panel (with just one GroupLayout then) and hide/show them based on user's selection. Hopefully, GroupLayout will adapt the size to the situation (after calling pack()).
If GroupLayout behaves well, then it would just be a matter of calling pack() each time after user changes his selection to show/hide extended fields.
Else you would have to manually set the size of your panel every time the user changes his selection.
Probably the easiest (good) way to do it is to add all the components to the main panel. Set the subpanels to non-opaque, and add the also to the main panel. The main panel the needs optimised drawing to be switched off.
Another technique is to add a spacer component. To the bottom panel add a component in the same column as the labels which dynamically takes the width component of its various size methods from the top labels. Do the same in reverse to the top panel.
I think there is no way to do it with the standard layout managers. You'll probably have to write your own layout manager, but it shouldn't be too hard if you subclass GroupLayout.
You could use GridLayout instead of GroupLayout which will give you uniform spacing between the columns
If you want to keep them in separate panels with separate layouts:
Iterate over all of the labels that you add, and find the maximum preferred width of each.
Iterate a second time, and set the preferred size to that each label's preferred height, but the maximum width.
This is the explanation of th GridLayout. This will set every component to the size, you expect it. With the GridData object you can specify how the components are ordere.
Examples
(source: sun.com)