So I'm having a class called Menu which extends JLabel and has a constructor which adds 3 JButtons to itself.
public Menu() {
this.add(jbutton1);
this.add(jbutton2);
this.add(jbutton3);
}
I have another class called GUI which extends JFrame and adds the JLabel to its contentPane.
public GUI() {
Menu menu = new Menu();
getContentPane().add(menu);
setSize(300,200);
setVisible(true);
}
The main method of GUI just looks like this:
public static void main(String[] args) {
GUI gui = new GUI();
}
So what I wanted is a JFrame with 3 JButtons in it (going to do more stuff later one). Instead I just got a blank JFrame. Why don't I see the JLabel with the 3 JButtons in it I added?
You're forgetting layout managers which are key to controlling how components are added to and sized by containers. JLabels are not used to being used as a container and holding other components and so come by default with a null layout -- no layout at all, making you the programmer responsible for sizing and positioning any added component.
Solutions:
Set your JButton's sizes and positions yourself -- a very bad solution since it leads to GUI's that only work well on one platform and that are difficult to debug and maintain
Or give the container (here the JLabel) a decent layout manager.
Or use another container, such as a JPanel, one that already has a layout manager, as the contentPanel. There are ways of getting a JPanel to display an image including overriding its paintComponent method.
You can find the layout manager tutorial here: Layout Manager Tutorial, and you can find links to the Swing tutorials and to other Swing resources here: Swing Info.
Related
I'm doing a program that is composed by multiple panels in a JFrame.
I need to do every elements in differents classes (It's because in my school, we need to have every elements separeated in different classes for clean code), but every example that I see with my kind of problem, they do everything in one class.
And I think that my problem comes from having multile classes so I show you my classes.
I have a panel in wich I need to put 2 panel, here is the code :
public class Inscription extends JPanel{
private PanneauBoutons panneauBoutons = new PanneauBoutons();
private PanneauFormulaire panneauFormulaire = new PanneauFormulaire();
public Inscription(){
this.setLayout(new BorderLayout());
this.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
this.add(panneauFormulaire,BorderLayout.CENTER);
this.add(panneauBoutons,BorderLayout.SOUTH);
this.setVisible(true);
}
}
And here is the Panel panneauFormulaire :
public class PanneauFormulaire extends JPanel{
private JLabel labelMatricule;
private JTextField zoneTexteMatricule;
public PanneauFormulaire(){
this.setLayout(new GridLayout(8,2,10,10));
this.setBorder(BorderFactory.createLineBorder(Color.black));
labelMatricule = new JLabel("Matricule : ");
this.add(labelMatricule);
zoneTexteMatricule = new JTextField(30);
this.add(zoneTexteMatricule);
this.setVisible(true);
}
So the problem Inscription don't appear on the main Frame if I don't do setBounds, but I want a BorderLayout...
(I tested and with a set bounds I can see the borders, so I think that it means the panel are really added to the Frame so why without setBounds I see anything?).
And the other problem is that the panel PanneauFormulaire don't appear on the Inscription panel...
So if I miss something, can you help me? thank you
And here it is the class that extends JFrame :
public class FenetrePrincipale extends JFrame {
private Container cont;
private Inscription inscriptionForm;
public FenetrePrincipale(){
super("IESN");
setBounds(100,100,1200,960);
getContentPane().setLayout(null);
setLocationRelativeTo(null);
setResizable(false);
...
inscription.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e){
cont.removeAll();
inscriptionForm = new Inscription();
inscriptionForm.setOpaque(true);
cont.add(inscriptionForm);
invalidate();
repaint();
}
});
You should NOT be using a null layout and setBounds(). Swing was designed to be used with layout managers.
but when I click on an option in the menu, the current panel need to be change by another one,
Then you should be using a CardLayout.
Read the section from the Swing tutorial on How to Use CardLayout for working examples. So download the example and use it as the starting point of your project. The code will be better structured then what you currently have and it is easier to change working code than it is to fix broken code.
so why without setBounds I see anything?
That is because you set your layout to null in getContentPane().setLayout(null);.
Java containers comes with a default layout which you are allowed to set to a different one. How the components are arranged in the container are dependent on the layout you use. The layout will directly affects the location, alignment, spacing, dimension, preferredSize of the components.
However, if you choose not to use any layout (.setLayout(null)). Swing will not know how you want the components to be arranged, hence you see nothing in your content pane.
Since you wanted "absolute control" over the components, you will be expected to set the bounds (location and dimension) of each added component manually by yourself. This is why you are not seeing any components (even if you already added it) until you set the bounds for them.
Java, elements don't appear in a Panel with a GridLayout or FlowLayout, but with a setBounds they do
Every layout has their own characteristics and for some of them the order of your codes does makes a difference. Hence, I will advise you to go through what each layout can do for you. Then, depending on your needs, choose one (or a combination of a few) and study how to use it.
And here it is the class that extends JFrame :
You probably won't want to extends to a JFrame. You can always make a customized Container like JPanel and add it to the frame.
(Why would you want to paint your paintings on a frame instead of a piece of paper?)
I have a hybrid swing application which can be run as applet or java application with the following structure:
public class Gui extends JApplet {
public void init() {...}
public void paint(Graphics g) {
...
g.drawImage(image, 0, 0, this);
}
public static void main(String args[]) {
JFrame frame = new JFrame();
JDialog dialog = new JDialog(frame);
Gui gui = new Gui();
gui.init();
gui.start();
dialog.add("Center", gui);
...
}
}
The whole gui consists of one drawing area which is continously updated.
I would like to embed a panel which is always on top and independent of the underlying drawing process.
I tried using JLayeredPane and add it between JDialog and JApplet, but Japplet cant be added to the Pane because it is a top level container.
I also tried realising it with the glasspane but no success at all.
Is there a solution without refactoring to much since the structure should be kept as far as possible.
Don't override paint() of a top level container, like JApplet or JFrame. Custom painting is done by overriding the paintComponent() method of a JPanel (or JComponent). Then you add the panel to the frame.
dialog.add("Center", gui);
The is not the way to add a component to a panel. Read the Container API to find the proper add(...) method to use. Also don't hardcode string values. Every layout manager contains variables that can be used as the constraint values.
I would like to embed a panel which is always on top and independent of the underlying drawing process.
Not sure this makes sense. If the panel is always on top, then it would cover the painting.
I tried using JLayeredPane
That sounds like the proper approach. You add the layered pane to the frame or applet. Then you can have a background painting panel and another transparent panel on top. Read the Swing tutorial on Using Layered Panes for a working example.
My issue is that I have two objects that have a "public void paint(Graphics pane)" class, and I want to add them both to a frame. I have the code in place to do so, but only the last die I add actually shows up. Any solutions / additional info you need to see?
The Add code:
public void addDice(Die userDie, Die computerDie) {
gameFrame.add(userDie);
gameFrame.add(computerDie);
}
And yes, the method is called and receives the two dice objects, and the object's class does extend "Component".
gameFrame is a Frame made with
Frame gameFrame = new Frame();
This is an AWT application, not Swing.
Thanks!
Is this a Swing application (JFrame) or an AWT application? Or something else? You may need to change your "Frame's" layout to GridLayout so that it can show both components. You will want to read up on use of the layout managers here
So I am working on a GUI application using the swing framework. In short, I have 3 JPanels that act as different views of my application. Now the problem is that no matter the order I add the JPanels to my JFrame, only the final JPanel I add resizes when I switch to that view.
Some relevant bits of code:
When creating the window, I first create each individual JPanel, and add it to the JFrame:
JPanel newPanel = new SomeClassExtendingJPanel();
this.jframe.add(newPanel);
Next, whenever I switch between views of the application, I hide the panel that is currently active:
jframe.validate();
jframe.repaint();
oldPanel.setVisible(false);
And then activate the to be shown panel:
jframe.validate();
jframe.repaint();
newPanel.setVisible(true);
Does anyone know what could be wrong?
To resize the JFrame with each swap, you could call pack() on it, but this is kludgy having a GUI resize all the time. A better solution is to use the mechanism that Swing has for swapping views -- a CardLayout. This will size the container to the largest dimension necessary to adequately display all of the "card" components.
Check out the CardLayout tutorial and the CardLayout API for more on this.
JFrame's ContentPane has implemented BorderLayout by Default, and there is possible to put only one JComponents to the one Area,
you have to change used LayoutManager or put another JPanels to the other Areas
I generate a bunch of JPanels and then pass them into a class that extends JFrame. How do I add an indefinite number of JPanels to this JFrame. I was also reading about JScrollPane should I incorporate this somehow into the design?
Example Code:
class foo extends JPanel
{
//generate JPanels
}
class bar extends JFrame
{
//grab some amount of foo classes and put them into this JFrame and show it
}
Also is there anything I need to watch out for when showing this JFrame?
Thanks
How do I add an indefinite number of JPanels to this JFrame?
CardLayout, JDesktopPane/JInternalFrame, JTabbedPane, JScrollPane - there are a number of options.
Also is there anything I need to watch out for when showing this JFrame?
(shrugs)
Construct and show GUI components on the EDT.
pack() the GUI before setting the position and calling setVisible(true).
Don't rely on the default layouts of content panes.
Don't implement custom painting in a top level container.
..
JFrame -> JScrollPane -> fathers JPanel then you'll decide which of LayoutManager will lay your bunch of JPanels, by defalut FlowLayout, don't forget to play with PreferedSize for childsPanels