Swing: "thin" standard component to act as a container? - java

I need to pick a standard container (JPanel?) in Swing that I can use as a placeholder to which I can add another custom component that extends JPanel:
JPanel containerPanel;
// built by a library from a text file, automatically part of a nice layout
MyPanel componentPanel;
// something complicated that I can't integrate with the builder library
containerPanel = builder.getMyContainerPanel();
componentPanel = new MyPanel(...);
containerPanel.add(componentPanel);
Is there a way to somehow couple the two panel sizes so that resizing works properly? I'm not quite sure how resizing works in swing, but what I want is for the outer containerPanel to be a thin wrapper that is subservient to my componentPanel and the outer panel delegates as much as possible to the inner panel.
I don't want to do things this way but it seems like the best way to decouple the builder library from my custom component.

I'd simply use a GridLayout.
containerPanel.setLayout(new GridLayout(1, 1));
This has the advantage that you can just add the sub panel without any parameters and it is guaranteed to use the entire area:
containerPanel.add(componentPanel);

You can use a BorderLayout and add your delegate container in the BorderLayout.CENTER position.

Hmm. Well, I decided to rewrite my component, so instead of a class that extends JPanel (inheritance), it uses composition and is constructed with an empty JPanel as a parameter + it adds child components to the JPanel. So I can use the builder library to build the empty JPanel, then later I pass that into my own component's constructor, so now I have 1 JPanel instead of two of them that I have to keep coupled together.

Related

Is it possible to have two gridbag layouts side-by-side inside a frame?

I'm using an extended JFrame class, called MFrame, to initialize two objects that extend JPanel. One JPanel has buttons, called ButtonPanel, and the other has a tree generated via reading in XML file, called TreePanel. I'd like to have them in two separate classes because I'll be adding a lot of functionality and I want to have them be as minimal as possible.
Inside both ButtonPane and TreePanel, gridbag is used to establish layout. I'm trying to display both within the same JFrame, but whichever one is added last, via ex. this.add(ButtonPanel), covers up the JPanel class behind it.
Has anyone been able to display two JPanel classes with Gridbag side-by-side within a JFrame? Any help would be appreciated.
Here is how:
Create a MPanel and add it to MFrame
Set its Layout to BoxLayout (horizontal in your case)
Add the TreePanel and ButtonPanel MPanel
You have to add a Panel because the default for JFrame is BorderLayout so add(...) is essentialy the same as add(..., BorderLayout.CENTER) thus only the last componet you add is visible.

Java - array of text fields not displaying

In my GUI class I have an array of textfields, which I initialized in this class constructor. The code is as follows
JTextField[] arrayOne= new JTextField [10];
for(int a = 0;a < 10;a++)
{
arrayOne[a] = new JTextField(String.valueOf(0));
arrayOne[a].setBounds(189 + a * 50, 156, 39, 23);
arrayOne[a].setVisible(true);
}
The problem is, that when I run my GUI, it does not show these text fields. Why not?
You should add the JTextField in the layout.
You should use add method of the container/or the class if you extend JFrame inside the for.
Read this.
Adding Components to a Container
When you add components to a panel or content pane, the arguments you
specify to the add method depend on the layout manager that the panel
or content pane is using. In fact, some layout managers do not even
require you to add the component explicitly; for example, GroupLayout.
For example, BorderLayout requires that you specify the area to which
the component should be added (using one of the constants defined in
BorderLayout) using code like this:
pane.add(aComponent, BorderLayout.PAGE_START); The how-to section for
each layout manager has details on what, if any, arguments you need to
specify to the add method. Some layout managers, such as GridBagLayout
and SpringLayout, require elaborate setup procedures. Many layout
managers, however, simply place components based on the order they
were added to their container.
Swing containers other than JPanel and content panes generally provide
API that you should use instead of the add method. For example,
instead of adding a component directly to a scroll pane (or, actually,
to its viewport), you either specify the component in the JScrollPane
constructor or use setViewportView. Because of specialized API like
this, you do not need to know which layout manager (if any) many Swing
containers use. (For the curious: scroll panes happen to use a layout
manager named ScrollPaneLayout.)
For information about how to add components to a specific container,
see the how-to page for the container. You can find the component
how-to pages using How to Use Various Components.
There is one more case for non visibility.
f.setVisible(true);
f.setSize(1000,1000);//Where f is the JFrame reference
Add the above statements after adding the JTextFields to the required Frame.

Layouts in desktop application

I am developing one java desktop application with a lots of panels with different and same layouts. Now when I want to set to panel new layout I always create new layout. E.G.
JPanel panel = new JPanel(new GridLayout(0, 1));
Is the correct solution to create some LayoutFactory and here create all the layouts that I need and then set to the panels?
1) laying JPanel by new GridLayout(0, 1) should be same as BorderLayout.CENTER or possible by using BoxLayout, in this case you place only one JComponent for whole JPanel
2) easiest way is lay JComponents by Nested Layout where each of Container can have different LayoutManager, same LayoutManager or their combinations
3) by using GridBagLayout or MigLayout is possible (in most of cases) place every JComponents once time for whole container or JPanel
hudi, if you want to make your code more concise, you can write helper methods which create and assign the layouts. If you are setting up layouts in only one class, the helper methods can be private methods of that class. Or if you are setting up layouts in various classes, you may be able to add protected helper methods to a common superclass (if you have one), or as static methods on a utility class.
Post the details of your code and we can give more specific suggestions.

The JPanel contentpane confusion

I am learning Java Swing and I appended a menuBar to the frame. By default this should call jframe.getContentPane().add(child). When I ran the script the menuBar didn't show up. But the button was at the very top "y=0" if that makes sense.
Then I realized my mistake I actually had to put in a menu in the menubar. Then the menuBar showed up. So that got me thinking...is the "menubar" "contentpane" actually 2 panels? It is confusing the hell out of me. Because that acted a lot like a panel. But getContentPane() returns a Container, not a JPanel object so I'm confused.
If so, does that mean that the only thing that is dumped directly into a frame are just Jpanel objects? Hence JButtons, JLabels are not directly in a frame...
Does that mean, jpanels are "nested"?
One more thing that is confusing me. If a jpanel can control how things are positioned, what is a LayoutManager for? :S
Thanks, and please answer as if to a 2yr old asking why the sky is blue,ha ;)
Some random thoughts:
Yes, JPanels and other components are often "nested". This is where a firm understanding of the Swing/AWT layout managers is essential.
While the type returned by a JFrame's getContentPane() is technically a Container, it's also a JPanel (which inherits eventually from Container).
I believe that you can make anything that derives from Container the contentPane, but you need to take care that it is opaque.
for that there is method
frame.setJMenuBar(menuBar);
for todays Java Swing GUI, is not neccesary declare ContentPane, from Java5, and with BorderLayout as default LayoutManager
then frame.add(myPanel);
//is same as frame.add(myPanel, BorderLayout.CENTER) and occupated whole Container
basic stuff about how to use LayourManagers
getContentPane() always returns a Container instance. However, you should note that JPanel objects are Container instances, as well as other classes in the Swing framework. The actual class of the instance returned is irrelevant, as you do not have control over which implementation of Container is used as a contentPane (unless you have forced a specific contentPane), and most of the time this should not be a problem.
You can add many GUI widgets in a JFrame, such as JButton, JLabel, etc. However, they will be automatically added to the associated contentPane.
JPanel does not handle the objects positioning, the LayoutManager associated with your panel does; either automatically based on its own set of rules (e.g. FlowLayout), or by using the constraints you have specified when adding the object to the container (the GridBagLayout layout manager is a good example). The JavaDoc on the LayoutManagers usually contain enough information to get you started on using them.
You can have nested panels, yes. A Container can contain other Container instances. While it seems to be a complicated solution, it does enable you to control exactly how your GUI is displayed. Depending on which LayoutManager you are using, on the needs you have to fulfill with your user interface, and on your own preferences/habits as a developper, you might need less or more nested panels.
You need to see this API doc for JComponent.
If you look at the inheritance hierarchy, you will see that the JComponent extends Component so a JComponent is a Component.
Also under Direct Known Subclasses, you can see the list of all the classes that extend the JComponent including JMenuBar and JPanel.
So, JMenuBar and JPanel are two more specialized versions of JComponent (or Container).

Best way of subclassing a JPanel in Swing

I am currently trying to build an expanding panel in Swing (akin the WPF's Expander control) and I'd like to retain the usual methods for manipulating it (i. e. setLayout, add, etc.). Only they should be routed to an embedded panel (the one being shown or hidden).
How would one do that? Overriding every method of JComponent and re-routing that to an embedded JPanel would be cumbersome, but that's the only way I see.
Or should I rather make the embedded panel visible to the outside and force users to use something like ExpanderPanel.getInnerPanel() instead. But then it's no drop-in replacement for JPanel which I think would be nice to have.
Take a look at the JXTaskPane from Swingx project. It already does what you need.
In 1.5(ish) Swing routed a few methods to the content pane in JFrame, JApplet, etc. Whilst there appeared to be some usability benefits for those just starting, it doesn't actually fix the problem. So everyone has to deal with a very strangely behaving API. So my advice is to avoid this approach.
If you have a Container widget which holds a panel you want to show and hide, why not layout your inner panel however you want, then add it to the Container panel, then use static methods against the Container to say
JPanel p = new JPanel();
//do something with the JPanel...
ContainerWidget.setContent(p);
ContainerWidget.expandPanel(p,true);
Would somethign like this work?

Categories