Best way of subclassing a JPanel in Swing - java

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?

Related

Do I need JPanel always?

I am now writing code simple GUI that's for start the game window. I only need Do you want to start game message and start button on the window. But I have a confusing concepts for the JFrame and JPanel. Actually, I thought I need to add JPanel to JFrame to add the other components such as JLabel, JButton,...etc. But I realized I don't actually need JPanel. I can just add the components simply use add(button), add(label) to JFrame. So why I need JPanel. And I think JFrame doesn't need JPanel but JPanel need JFrame. Am I understand correctly?
No, not always. A simple graphical user interface may be implemented by just adding components "directly" to a JFrame. But in order to get more flexibility, you would always use JPanels. For example, to employ different layouts in different parts of the GUI, to group certain components together, etc.
A JFrame is backed by a JRootPane, a part of which is a contentPane.
(image from Oracle Javadoc)
When you add components to a JFrame, you are really adding them to the content pane, e.g.: frame.getContentPane().add(Component).
A JFrame is a common starting scene of a Swing GUI application, while a JPanel is intended to be put in another scene (container). Since both content pane and a JPanel inherit from the same class (Container) you may use them in a similar manner, as far as adding components to them goes.
Do I need JPanel always?
No. Well, unless you need a Swing GUI. Then yes.
Another answer replied words to the effect. "No, you can add components direct to a frame" What they missed was that components added to a JFrame are added to the content pane (automatically). The content pane is a JPanel.
Having said that:
I (and many others) would recommend designing an app based around a main content panel, then adding that panel to a top-level container as needed. The top level container might be a JFrame, JWindow, JDialog, JOptionPane ..
What prompted the question? A JPanel is a very 'light weight' container (in more ways than one). A GUI can contain 1000s and not be burdened by doing so. Of course, that's a rare requirement, but just saying .. use panels as needed and don't worry about it.

JFrames inside JFrames

I currently have build an application where I use multiple frames.
But it would be nice if I could use the frames I used all in just 1 frame.
Like in the image below.
So if you press the left button "Speler Overzicht" that it will show the users in the right panel and I still have my buttons in the left panel.
Generally speaking, it's a very bad idea to base you UI classes on JFrame, as it locks you into a single use case, meaning you can't add the UI component (frame) to other containers.
I better solution is to base your UI components on JPanels, which then allows you to add them to where ever you need them. It also makes life easier to extend them, but that's another story.
To allow the user to move between multiple views, you can use either a CardLayout or JTabbedPane depending on your needs
See How to Use CardLayout and How to Use Tabbed Panes for more details
Use JPanels instead.
buttonPanel=new JPanel();
overzichtPanel=new JPanel();
buttonPanel.add(button);// do this for every button
overzichtPanel.add(componentsYouWantToAdd);// replace with your variables of course
frame.add(buttonPanel, BorderLayout.WEST)
frame.add(overzichtPanel, BorderLayout.CENTER)
You cannot put one JFrame inside another. You have a some design choices here. You can change your JFrames to JPanels. This is probably the easiest change. On the other hand, you can look at using Internal Frames instead.

Switch to specific JPanel using Cardlayout

I've started working on a Java desktop application using netbeans. I have 7 different screens and to represent them I am using JPanel. One JPanel to represent each of them and one to contain all of them(named as mainPanel), which is inside a JFrame. mainPanel uses Cardlayout for the purpose of switching between screens(JPanels). I built all this interface using netbeans ui widgets i.e. drag drop.
LayOut
JFrame
mainPanel (Jpanel) CardLayout
Child1 (JPanel)
Child2 (JPanel)
.
.
.
.
Childn (Jpanel)
I know that one can switch screens using JPanel.next() and Jpanel.previous. but they can only be used when switching is to be done among consecutive screens i.e. if you have to switch to an immediate neighbour. There's also a method JPanel.show() to go to a specific screen but problem is that it takes a parameter name which is a String you associate when you add it to mainPanel using JPanel.add() function. I've added everything using drag and drop, so I don't know what String gets associated, if it does.
Although it looks very primitive and I've already done it without Cardlayout but this time, Cardlayout is a requirement.
Help will be highly appreciated
This example uses a JComboBox to change cards. The example extends JPanel to add a name, but Component has getName() and setName() methods as an alternative. See also this related answer.
Well... I got the answer.
The thing is, when you add something through interface, code for it is autogenerated which is hidden by default. So, I had to look into the autogenerated code for associated string. by default it is card1, card2, card3 and so on.
The example in answer by trashgod is exactly what I want but not the way i want. It has manually associuated the string in custom Jpanel. But it made me think of looking into the autogenerated code. So, thank You very much :)
Now what I need to do is like
mainPanel.show (gameHome, "Card3");
As an alternative, use a ViewSwitcher
It's better suited for what you are trying to do here.

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).

what's the use of a frame , a pane or a panel in swing?

I read that JFrame is made of several panes ..what are panes and why is Jframe made of panes ?
And why there is a JPanel while it seems that the JFrame looks exactly like the JPanel but with a menu bar and a close button so what's the need for a JPanel ? Can anybody explain to me clearly the definition and use of those 3 components ?
There are top level containers such as JFrame. These can serve as the main window in which a GUI is built.
Then there are intermediate level containers. These must be placed in other containers, they cannot exist by themselves. They either help you organize components or they add functionality. A JPanel is a very simple container that helps you to organize other components. While a JSplitPane adds the functionality of having two panes that are variable sized.
When you have a complex GUI you may want to use JPanels to organize various areas of your GUI and then add each of the panels to your JFrame.
In Java the Swing API makes use of the Composite Design Pattern. This means that you can compose very complex objects from other objects and still treat the composite objects the same way as the simple objects. So you can put a JPanel into a JPanel and it still behaves like a JPanel.
Think of it like a tackle box (or sewing kit). It is made of a big container. But rather than put many small objects into this big container and make it difficult to manage later you can place some smaller compartments inside the big box. Then hooks and sinkers etc go in the compartments. Its easier to manage. The big box is the JFrame and the compartments are the JPanels.

Categories