I want to store components like JButton, JTextField, JTextArea etc. all in same ArrayList and later loop through it and add every component to JFrame. I tried storing them in ArrayList but when I looped through it and added every component it included to my frame, nothing showed up in frame. Does anyone know how this can be done? Thanks in advance.
go ahead with this:
public class Example {
public static void main(String[] args) {
JFrame frame = new JFrame();
List<Component> components = new ArrayList<Component>();
components.add(new JButton("test1"));
components.add(new JButton("test3"));
components.add(new JButton("test3"));
frame.setLayout(new FlowLayout());
for(Component component: components)
frame.getContentPane().add(component);
frame.pack();
frame.setVisible(true);
}
}
add a layout manager to your frame
call pack() to resize the frame according to your components
set the frame visible
Try declaring the ArrayList like this:
List<JComponent> = new ArrayList<JComponent>();
The above works because JComponent is a common ancestor for JButton, JTextField, JTextArea - that is, it's a super class common to all JComponents.
It's not clear to me: why do you want to add the components first to an ArrayList? add them directly to the JFrame.
Do you know how to use Layout Managers?
A layout manager is an object that implements the LayoutManager interface* and determines the size and position of the components within a container. Although components can provide size and alignment hints, a container's layout manager has the final say on the size and position of the components within the container.
Using Layout Managers
Related
I tryed to learn about GUI and tryed to create the window with two buttons and jne Label on the screen. But I don't understand why I can't see these elements simultaneously. When I comment out lines for buttons I can see the Label element.
Here is my code:
import java.awt.*;
import javax.swing.*;
public class MyWin {
public static void main(String[] args) {
JFrame w = new JFrame("My Window");
w.setSize(1000,800);
w.setVisible(true);
JButton b = new JButton("My button");
b.setVisible(true);
b.setSize(150, 100);
b.setLocation(500, 20);
JButton b2 = new JButton("Second button");
b2.setVisible(true);
b2.setSize(150,100);
b2.setLocation(500, 600);
JLabel l = new JLabel("My label");
l.setVisible(true);
w.getContentPane().add(b);
w.getContentPane().add(b2);
w.getContentPane().add(l);
}
}
The default layout for the JFrame is BorderLayout and when you add your JLabel through single parameter add method you add it with a BorderLayour.CENTER constraint as a default, this causes to fill all the available space. So you might want to use layout manager suitable for your needs, then the components won't overlay themselves.
Visual Guide to Layour Managers
First of all, JFrame uses BorderLayout as a default layout and just adding the components (w.getContentPane().add(b)) sets them in BorderLayout.CENTER; where they occupy the whole JFrame to fill the empty space. Thus, is recommended to add components in a JPanel. So, you should create first a JPanel, add the components to the JPanel and finally add it to the JFrame.
The setSize(...); statement is not applied due to the default layout (FlowLayout) in JPanels and also is discouraged. (Because it won't work properly in different computers with different screen resolutions)
If you want to change the size of the components you should change the default layout and use instead a customLayout, borderLayout, gridLayout...
If you want to understand deeply how layouts work and all the available layouts in Java check this
I am making simple login screen. I added two JLabel's in JFrame in my program and it's running successfully but the problem is that when I run the program I got blank screen and empty jframe, however I have added two jlabel's in that frame but it's not showing me any thing and then if I minimize the window and after some time if I open that window again then I can see those components.
Here is my code:
package javaapplication41;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.*;
public class JavaApplication41 {
JavaApplication41()
{
JFrame cpec=new JFrame();
cpec.setBounds(300,200,600,350);
cpec.setUndecorated(false);
cpec.setVisible(true);
cpec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel l = new JLabel(new ImageIcon("C:\\Users\\MUHAMMAD SHAHAB\\Documents\\NetBeansProjects\\Real Estate\\src\\real\\estate\\file (2).jpg"));
l.setBounds(100,100,200,125);
//l.setLayout(null);
cpec.add(l);
JLabel kiq=new JLabel(new ImageIcon("C:\\Users\\MUHAMMAD SHAHAB\\Documents\\NetBeansProjects\\Real Estate\\src\\real\\estate\\bla.jpg"));
kiq.setBounds(100,100,100,100);
//kiq.setLayout(null);
l.add(kiq);
}
public static void main(String[] args) {
JavaApplication41 ne=new JavaApplication41();
}
}
I am getting this output when I run program:
and when I minimize this window and again open this, then I am getting the desired output here it is:
what am I doing wrong?
You have to put cpec.setVisible(true); after adding all the items in your jframe.I hope this will surely solve your problem
You have set the visibility of JFrame at a very early stage. At that time the JLabel was not added. When you minimized and resized your frame, it got rendered again resulting in showing your added components.
Remember to add components before setting the Frame's visibility( set visibility at last).
Also I would suggest you to use GUI threads when working on swing components. Refer to swing utilities here : https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
Lastly set the layout of JFrame to null as you are trying to add labels to specific coordinates with setBounds() method.
Default layout of jframe is BorderLayout, so if you want you can change layout by reference of java.awt.Container abstract class.
It is initialized by getContentPane() of javax.swing.JFrame class.
The components are added only through reference of java.awt.Container class.
java.awt.Container c=cpec.getContentPane();
c.setLayout(new FlowLayout(FlowLayout.LEFT));
c.add(l); //label will get added to JFrame instance that is referenced
//then define size and at last define visibility
cpec.setSize(500, 500);
cpec.setVisible(true);
Set the Layout manager of the container as null. By default it uses BorderLayout as its Layout manager. You just have to call the getContentPane() method using the reference of the JFrame, which returns a container reference. Example:
Container c = frame.getContentPane();
c.setLayout(null);
For more information you can go through my Website.
I am a beginer and I dont know how to add more objects into JFrame.
How could I add more than one JPanel objects into JFrame?
Below is what I have tried.
Thanks for your help.
public class Init extends JFrame{
public Init(){
super("Ball");
Buttons t = new Buttons();
JumpingBall b1 = new JumpingBall();
JumpingBall b2 = new JumpingBall();
t.addBall(b1);
t.addBall(b2);
add(b1);
add(b2);
setSize(500,500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
}
Assuming that JumpingBall extends JPanel, you might want to have a look at the java layout managers here: Link.
The default Layout for a JFrame is the BorderLayout and if you didn't specify where you want to add your component, The BorderLayout will put it in the center by default. In BorderLayout, you cannot have more that one component in the same area. So, in your example you will end up having only the second JumpingBall panel in your frame. If you want to have more than one component at the center, then you will have to create a JPanel and add those components to it using different Layout. The common three Layouts are the BorderLayout, FlowLayout and GridLayout Please have a look at the provided link above to see how the components are arranged.
You can add a number of JPanel objects in a JFrame, using the add method. If only one is displayed, you might need to change your Layout options or use a Layout Manager (Look here for more).
You are seeing only one because it overlapping each other. Just provide setbound(x,y,x1,y1) for you panel component and you will see your panel at location.
or use setLayout(new FlowLayout()); which is going to order your component in respective to other so you will not override each-other.
http://pastebin.com/VaaTRsuf
I would like to have the JList and JTextArea resize with the window, but the JPanel stays in the center.
Your LogView class extends JPanel and thus unless you change it, it uses JPanel's default layout, FlowLayout. Components held in a FlowLayout-using container do not change size when the container changes size, and so if you want this behavior, you don't need a component Listener -- you just need to change the layout manager for the LogView JPanel to BorderLayout or something similar that allows its held component to expand, that's it. One line of code:
public LogView(final JFrame contentPane) {
// .......
setLayout(new BorderLayout()); // add this, that's it
add(mainPanel);
}
Another option is to get rid of mainPanel as it doesn't appear to be necessary at all, to set the layout of your LogView object to be GridBagLayout and to add your components directly to the LogView object.
To put it simple, there's a simple java swing app that consists of JFrame with some components in it. One of the components is a JPanel that is meant to be replaced by another JPanel on user action.
So, what's the correct way of doing such a thing? I've tried
panel = new CustomJPanelWithComponentsOnIt();
parentFrameJPanelBelongsTo.pack();
but this won't work. What would you suggest?
Your use case, seems perfect for CardLayout.
In card layout you can add multiple panels in the same place, but then show or hide, one panel at a time.
1) Setting the first Panel:
JFrame frame=new JFrame();
frame.getContentPane().add(new JPanel());
2)Replacing the panel:
frame.getContentPane().removeAll();
frame.getContentPane().add(new JPanel());
Also notice that you must do this in the Event's Thread, to ensure this use the SwingUtilities.invokeLater or the SwingWorker
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.
Remember, Java use 'copy reference by value' argument passing. So changing a variable wont change copies of the reference passed to other methods.
Also note JFrame is very confusing in the name of usability. Adding a component or setting a layout (usually) performs the operation on the content pane. Oddly enough, getting the layout really does give you the frame's layout manager.
Hope this piece of code give you an idea of changing jPanels inside a JFrame.
public class PanelTest extends JFrame {
Container contentPane;
public PanelTest() {
super("Changing JPanel inside a JFrame");
contentPane=getContentPane();
}
public void createChangePanel() {
contentPane.removeAll();
JPanel newPanel=new JPanel();
contentPane.add(newPanel);
System.out.println("new panel created");//for debugging purposes
validate();
setVisible(true);
}
}
On the user action:
// you have to do something along the lines of
myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()
myJFrame.getContentPane().add(newContentPanel)
myJFrame.getContentPane().revalidate()
Then you can resize your wndow as needed.
Game game = new Game();
getContentPane().removeAll();
setContentPane(game);
getContentPane().revalidate(); //IMPORTANT
getContentPane().repaint(); //IMPORTANT
It all depends on how its going to be used. If you will want to switch back and forth between these two panels then use a CardLayout. If you are only switching from the first to the second once and (and not going back) then I would use telcontars suggestion and just replace it. Though if the JPanel isn't the only thing in your frame I would use
remove(java.awt.Component) instead of removeAll.
If you are somewhere in between these two cases its basically a time-space tradeoff. The CardLayout will save you time but take up more memory by having to keep this whole other panel in memory at all times. But if you just replace the panel when needed and construct it on demand, you don't have to keep that meory around but it takes more time to switch.
Also you can try a JTabbedPane to use tabs instead (its even easier than CardLayout because it handles the showing/hiding automitically)
The other individuals answered the question. I want to suggest you use a JTabbedPane instead of replacing content. As a general rule, it is bad to have visual elements of your application disappear or be replaced by other content. Certainly there are exceptions to every rule, and only you and your user community can decide the best approach.
Problem: My component does not appear after I have added it to the container.
You need to invoke revalidate and repaint after adding a component before it will show up in your container.
Source: http://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html
I was having exactly the same problem!! Increadible!! The solution I found was:
Adding all the components (JPanels) to the container;
Using the setVisible(false) method to all of them;
On user action, setting setVisible(true) to the panel I wanted to
show.
// Hiding all components (JPanels) added to a container (ex: another JPanel)
for (Component component : this.container.getComponents()) {
component.setVisible(false);
}
// Showing only the selected JPanel, the one user wants to see
panel.setVisible(true);
No revalidate(), no validate(), no CardLayout needed.
The layout.replace() answer only exists/works on the GroupLayout Manager.
Other LayoutManagers (CardLayout, BoxLayout etc) do NOT support this feature, but require you to first RemoveLayoutComponent( and then AddLayoutComponent( back again. :-) [Just setting the record straight]
I suggest you to add both panel at frame creation, then change the visible panel by calling setVisible(true/false) on both.
When calling setVisible, the parent will be notified and asked to repaint itself.
class Frame1 extends javax.swing.JFrame {
remove(previouspanel); //or getContentPane().removeAll();
add(newpanel); //or setContentPane(newpanel);
invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate();
repaint(); //DO NOT FORGET REPAINT
}
Sometimes you can do the work without using the revalidation and sometimes without using the repaint.My advise use both.
Just call the method pack() after setting the ContentPane, (java 1.7, maybe older) like this:
JFrame frame = new JFrame();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
....
frame.setContentPane(panel1);
frame.pack();
...
frame.setContentPane(panel2);
frame.pack();
...