Disclaimer: I am new to swing.
TLDR:
I am dynamically adding JPanels to an "enclosing" JPanel with a button. All panels use MiGLayout. The outer panel contains one cell only, and more rows are created as inner panels are added, top to bottom ("flowy" constraint). The inner panels are made of two rows --but the second one is revealed dynamically ("hidemode 3" layout constraint, with setVisible(false) until a condition is met.)
What's happening, is when adding an inner panel, and causing its second row to be visible, it overlaps with the panel below it. I have tried to call revalidate and repaint everywhere possible. To me, it would seem that the outer/enclosing panel simply has to revalidate its child components, but this doesn't seem to be happening.
Background
I am using MiGLayout and Swing to create a GUI for importing to my database.
Users should be able to hit a button which adds panels to an enclosing panel.
Specifically, the [portion of the] GUI [in question] is made of...
an enclosing JPanel(black), containing a:
JToolbar(blue) and
JScrollPane(red), which has as its Viewport
another JPanel(green)
this last JPanel, #4, is a container for dynamically added panels via a button (see the second picture below).
The bottom most JPanel, #4, uses MiGLayout. Itself, and the scroll pane that contains it, are hidden from view until a user hits that button next to the "File" comboBox. (not shown in picture above, as that wasn't runtime).
Once pressed, a subclass of JPanel is added to this panel:
(runtime screenshot)
The panels are stacked on top of eachother as more are added.
This inner panel is made of two rows, but the second one is invisible and does not affect the layout until it is visible. It is made visible via listeners once a condition is met within the text field..
The issue
If the second row of an inner panel becomes visible, it overlaps the panel in the row under it. Here's what I mean....
User adds three panels:
Second panel triggers setVisible(true), so now is made of two rows, but hides the third panel:
For dramatic effect (same runtime):
The problem is obvious. How do I prevent this overlap?
Ideally, I'd want the out panel to reorganize itself appropriately to account for the larger size.
Say I add one panel, then trigger the hidden row, THEN add another panel --- there is still overlap. It was my understanding that revalidate() should take care of these things but I have called it every place possible (perhaps too much, if possible??) to no avail..
I have tried many different constraints on the enclosing panel as well as the inner panels, with no luck. I have tried both creating the second row and show/hiding it dynamically, or simply creating it dynamically, with no luck. It consistently overlaps the same way, and I cannot get it to re-layout these inner panels.
I can think of some work arounds, but this seems like it should be possible!
My longest question ever, sorry for that. Any help is appreciated.
Thanks.
It turns out that setting row constraints on the (green) outer panel was what was causing the issue.
I had set min/preferred row size to 30 pixels, with a maxiumum size of 60 pixels (60 being the size of a two row inner panel). Clearly this did not do what I thought it should.
I had heard to be wary using pref/max/min bounds in swing---but I ignored it and this is what happened!
By removing the row constraints completely, the outer (green) panel shifts the rows and what not appropriately.
jframe.getContentPane().revalidate();
Related
I have two JPanel instances in a JLayeredPane, on different z-orders. I want both of my child JPanels to always fill the space of the LayeredPane.
The idea is for me to toggle the display of a 2nd panel over top of the first to display a modal-like dialog. Yes, I could just use a JDialog, but I thought it would be fun to try and create some transparancy overtop of the covered JPanel for a nice effect.
I find that using a layout manager on the JLayeredPane, like BorderLayout, and trying to set both children to CENTER conflicts since both panels can't be in the Center.
Is there a trick that I'm not seeing?
The idea is for me to toggle the display of a 2nd panel over top of the first
The easiest way to do this is to use a Glass Pane.
Check out the Disabled Glass Pane for an example of this approach.
There are two ways to create some "Glass Panel like" overlay for JPanels with JLayeredPane:
Add a ComponentListener to the JLayeredPane and update the sizes of all child components whenever the size of the JLayeredPane changes
Create a simple FillLayout, which expands the size of its child Components to the size of the Layout Container (In our case the JLayeredPane). You need to keep a list of children Components. During layoutContainer you copy the dimensions of the Container to these child Components. I wrote this and its really simple, but unfortunately I can't post it, since it's corporate. But if anyone is interested just ask in the comments. The implementation basically consists of one-liners.
For both solutions you need to make sure, that the panels on top are transparent, by setting setOpaque to false. This ensures that underlying panels render their content.
I noticed when adding multiple panels in JFrame content pane, if you set all the panels to be visible, you going to see (with set different background color ) some of them overlapping each other. I wanted to know if it is possible to have one master panel, that even though you add extra panels, that one panel from before will remain on top of all them?
Using Eclipse Juno for Java & WindowBuilder
I have three panels of the same size that lay on top of each other - they have different widgets. During coding, they all display and clutter up what I'm doing.
I can show and hide them in runtime as needed but, I want to display only the one I'm working on while doing drag and drop of widgets. I've tried using different panels and pane types (tabbed, layered...) and selecting opaque but, nothing hides them.
How do I hide the other (panes, panels...etc) during coding?
I have the same issue. Among other reasons, my solution was to create separate classes per view. So my frame would be its own class, it would maybe have a TabbedPanel (or whatever it's called), and then I would have a new class for each tab on that tabbed panel. Each class would extend JPanel so I could plop it right in there. That way not only is your gui design not cluttered up, but your code logic is separated into separate files, where it might belong anyway.
[SOLVED] Answering my own question.
It may not be perfect or the best/correct way, but it works!
WindowBuilder wants to Surround other panels/widgets that are within it's bounds so, you have to trick it by using opaque, Order>forward/backward then setting the desired bounds (all panel sizes and bounds can be equal and will overlay nicely both during widget drag&drop and runtime).
Here's how to do it with a 3-Panel example (NOTE: WindowBuilder is buggy/in-consistent and often I needed to select the items from the gui, not in the Components tree).
Create your first panel. Add your widgets and border to it.
Create your second panel (the one you want to overlay on top of the first one). This second panel MUST not be completely inside the first panel - it MUST extend beyond the edges of the first panel (parts of it can be inside the first panel). This takes a bit of trial because of the 'surround', mentioned above. Use the shift-key to stop the snapping.
Select the top panel in the gui, NOT from the Components tree, and toggle the Opaque property. The top panel (first or second) in the tree is the one you set to opaque and work on.
Add another panel and repeat the process.
Once you get your widgets/etc as you want them, use the property Bounds to set them all the same or as desired. After that, as long as you don't move a panel by dragging it, it will remain un-surrounded by the other panels. If you move by dragging, it may get set to surround...
I've done this a dozen times now and it works consistently.
Below is a shot of 3 panels overlayed, un-surrounded and not opaque, thus showing widget clutter
Below is a shot after the bounds are set (and not surounded). Opaque and order not yet set:
Below is a shot with bounds set and panel 3 moved forward and opaque set:
Below is a shot with bounds set and panel 2 moved forward and opaque set:
... etc, etc... Now you can work on a panel that's ordered to the front and, naturally, use the setVisible in your code...
I don't really have example code for this (so I'll try to explain it), but I'm wondering if there is a way to stop JSplitPane from mashing my layouts?
I have two panels that I add into a JSplitpane which both have GridBagLayout on them. On the left pane I have a table. On the right pane I have a JPanel that displays information when the user interacts with the table. However, when the information is displayed on the right pane, the table gets mashed. (unable to display unless the divider is dragged all the way to the right).
I would think with a GridBagLayout that my table should still be visible no matter what. Even if it squished the columns and rows in.
I'm just wondering if this is a common problem, if so, is there a fix?
My issue was that when the table was clicked I reset the constraints to the JSplitPane. This caused the constraints to disappear and leave the GUI to do what is pleased.
Pseudo:
//set constraints for panel that contains table and random components
//if table clicked add data (with GridBagLayout) in other side of splitpane <-- this is where I accidentally reset the layout
So as soon as that line of code was removed, it functioned as expected.
I meet a relayout problem that is in my swing application I add four components (two JLabels, one JTextField and one table, each occupies one row) to a panel by using GridBagLayout, for some logic, I need to make one label visible true or false based on some conditions, but when I invoke setVisible(false) the components below this label will come up a little and when I invoke setVisible(true) they come down a little which makes the GUI flashing. Are there any methods which can make other components stick on the panel? Thanks.
Instead of setting the label visible or not, you could just change the text between the default and "". The Label would still stack the same height but no text would be visible.
How about TableLayout with fixed columns and rows?