Java GUI - Changing inside JPanels dynamically - java

Trying to figure out if it's possible and difficultly level around the below problem as depending on such might consider other alternatives...
If I have a overall JFrame framework, can I construct various different JPanels with their associated components and actions then say pass these JPanels as args depending on user interaction so the inside of the overall JFrame/JPanel changes. I'm assuming there must be some implementation that achieves this, but having trouble find the answer.. For example I construct a JPanel, which has border layout, and the centre position will change different JPanels depending on what a user does etc.. I thought it would be a simple as create a JPanel, then passing it to a method which calls the overall Jpanel add(component, borderlayout.center) method which would change what is shown, but doesn't work like that and assumed that must only work for constructor when GUI is first constructed..
Sorry for the length, but if someone can point me in the right direction i'd be appreciated...

Removing and adding components does work as expected. You need to call revalidate() on the parent component once it's done, though.
If that doesn't work, post an SSCCE exhibiting the problem.

Related

Layout Manger to Freely place your objects

I am a self-taught java developer and I use IntelliJ IDEA for Java. Recently I saw a video on youtube in which the guy was using NetBeans and in his JFrame form, he was able to freely place his objects like JButton, JTextFeild, JLabel, etc. I am not able to figure out how to do that. In IntelliJ IDEA I found several layout managers such as Border, Card, Grid, Bag, etc. but none of them gave the desired result. can somebody please tell me how can I get a layout manager in which I can freely place all my objects and also freely resize them without any restrictions? Thank you in advance for any help.
In swing every component extends Container. That means that every component can have nested components (they all have add(Component) method). However, not all of them support the layout-ing of nested components.
What I want to say is, that you can add a component to a JButton, but a JButton is not capable of showing its nested components.
So, in order to have nesting, we use the components - containers that support the orientation of their nested components.
These components are all windows (JFrame, JDialog, etc...) and JPanels. There some others that support layout-ing a specific type of nested components. For example a JMenu is capable of showing JMenuItems properly.
Now, these "top-level"/empty containers are using Layout Managers in order to align-show their nested components. Based on the container's layout manager, the components are shown.
This is why you can't "freely" place the components into a JFrame. Because its Layout Manager is taking care of the components will be placed. So, what you are looking for, is to change its LayoutManager (use setLayout method) to one that allows you to freely place the components.
Guess what? There is no such layout manager. Simply because, it would have nothing to do/calculate since you are taking care the layout of the components. So, in order to achieve the "free" component layout, you must use jframe.setLayout(null);. In order to layout the components after it, you will have to use componentInsideJFrame.setBounds(...) and give it constant coordinates /dimension.
This is bad practice. A very bad one when it comes to UI. Giving a component static coordinates and dimension is bad. There are some questions you have to ask yourself.
What if user resizes the window? If the window is 301x301, the center of it, is at (150,150). So you place a component at (150,150). Ok it works. Now user resizes the window and makes it 501x501. The center is now standing at (250,250). But the component is staying at (150,150). There is the solution of setResizable(false), to this kind of problems, but how often have you used "uncapable of resizing" applications? What if user wants to resize it?
I hope you get it and understood what I am trying to say.
By using layout managers, you are solving this kind of problems easily, since the layout manager will take care of the resize and calculate the new center.
Yes. I know it feels weird, but all these youtube tutorials are not teaching you the correct way to make Swing GUIs. (This is a conversation for another day, I guess)
I truly suggest you read the tutorials of Swing documentation in order to get some ideas of how layout managers work. You will really benefit from those.
Finally, I suggest you to leave outside the whole "gui-builder-tool" thing. They seem to help you building your GUI, but they are adding so much additional/useless code and most of the times they are "bad UI creation" prone. Try to code the GUI by yourself.
At first, this sounds a bit harsh, but you can always run your application and see the result of the GUI. After some mistakes, you will finally be able to imagine the GUI result by only seeing the container.setLayout(..) and container.add(...) lines.

Method called when layouting is done?

I'm looking for a method that I could override or some listener that is fired when a JPanel is being layouted. Checked the javadoc but couldn't find one. The situation is this:
I have a component that takes care about its contents via a Null-Layout.
The component itself is however layouted inside another JPanel (with a layout manager) and receives a certain size when layouting is done.
Now I want to use this size to calculate widths and heights of the contents of that Null-Layout JPanel.
But of course I need to know when I have to recalculate sizes. Any ideas or a good alternative approach? The required calculating in the Null-Layout is actually very simple and using a layout manager would probably require more work than the current solution - I just need to find that method or listener.
Answering myself so this can be closed.
doLayout will be called when layouting is needed, so that's the method one can override when doing layouts without a layout manager.

What's the difference between setVisible(true), repaint() and validate()?

I create a little program that load a frame in which I added some panels.
When I click on some button it should show some panels and hide other.
I'm experiencing some difficult to do it, even because I don't really figure out the diference between setVisible(true), repaint() and validate() (that some friends of mine suggested to me).
I hope you can make me to understand!
Thank you.
Carefully read the API for JComponent. The usages are:
setVisible - it will hide or show your component altogether. If you set it as false, you won't see it at all.
repaint() - is called when the actual pixels need to be redrawn, this is done automatically. It's used, for example, when you move a window on top of your GUI and then move it away. The part that was covered needs to be redrawn.
validate() - you should call this when the layout of your GUI has changed and you need the manager to replace and redraw your GUI.
It's a bit more complicated than that, so again, carefully read the API.
setVisible(true): sets the component so that it's visible.
repaint(): calls the paint method on the component.
revalidate(): updates the component based on the root component

purpose of JPanel?

This write up on JPanel seems to focus on this container as a means of setting a background color. Oracle on how to use JPanel Should I infer that if I am happy with the default grey background in ubuntu/gnome/Java programs, there is no need to use this object? Is there an object-oriented programming reason to use this object?
JPanels are a way to create a logical "division" of space if that makes any sense. For example, if you think about HTML, you could just put elements one after another on the page (how some old HTML pages look in fact) but it's much more aesthetically pleasing to use a container like a table, or some CSS styled DIV tags to create divisions on the page, and place elements relative to one another in a much more defined manner.
JPanels fill this function in Swing, where each JPanel has a Layout Manager that defines how it's inner elements are laid out. It's not unusual to nest JPanels, for example, using a JPanel with a border layout for the menus/status bar, etc, a JPanel at the center of that with further elements, and then additional JPanels inside of that central "content panel" area that further divides the space, for example, creating an input form on one part of the central panel.
In this sense, JPanels are quite comparable to how Tables and Divs are used in HTML, and you should think of them in a similar manner when creating your layout. The most important thing about JPanels is their ability to dynamically resize, pushing the contained components around. If you just used, say, one JPanel and absolutely positioned everything, then you'd lose the main appeal of Swing, and this container methodology.
It's quite possible you perceived the authors angle to be one slanted towards color and drawing, but I think if you give the blog a second read you will find that he was indeed trying to be more expansive than that. JPanel's can and are used as content panes for a variety of other widgets in a typical Swing application.
Also I'm not sure why you reference Ubuntu/Gnome, as the L&F of a platform is quite divorced from the utility of JPanel.

JPanels, Listeners and Threads

For a school project I'm writing a BlackJack card game in JAVA.
After a few steps within the program, my whole computer system slows down/stutters and some areas within the JFrame turn black. No repainting seems te be happening.
I will give you some program details in words rather then submitting the code.
I have done some extensive extending of almost every GUI component to give it the look and feel that I want. Almost every child of JComponent that I use has got its paintComponent rewriten with custom image backgrounds and anti-aliasing where applicable.
In my (custom) JFrame I load an extended version of JPanel. This panel holds all the GUI components for that screen. When I want to switch screen (go to a different part of the program), I switch to another extended version of JPanel. I do this by removing all elements from the JFrame and add the new panel. These different panels implements ActionListeners and FocusListeners.
At this point my thoughts are leaning towards a thread handling issue. My theory for the moment is this: When a panel is constructed for display in the JFrame (each on different stages within te program), the previous constructed panels aren't realy 'destroyed', and the Listeners of those panels remain active.
My question for you people is, wether this theory holds ground... And in that case, is there a way to 'kill' these panels or at least stop the listening?
If my theory doesn't make sense, what else could be causing these symptoms? Could it be the extensive overwriting of the paintComponent methods?
Any ideas would be highly appriciated!
Regards Wilco
When a panel is constructed for display in the JFrame (each on different stages within te program), the previous constructed panels aren't realy 'destroyed', and the Listeners of those panels remain active.
No. Events are only dispatched to the component that has focus. It a comonents doesn't have focus then it won't received system generated events like KeyEvents and MouseEvents. So if a panel isn't visible then it won't receive events.
I switch to another extended version of JPanel. I do this by removing all elements from the JFrame and add the new panel.
This is not the best design. It is better to use a Card Layout which was designed for this purpose.
Almost every child of JComponent that I use has got its paintComponent rewriten with custom image backgrounds and anti-aliasing where applicable
Then you probably have problems with your custom painting. What happens when you just use the standard components without custom painting?

Categories