I'm building a GUI that uses a CardLayout to switch between screens. I want one of the screens to have a graphic on it. I've successfully been able to put a rectangle onto a panel with a GridLayout, and put that panel onto a main panel, and a rectangle is clearly visible. However, when I to put that panel onto a CardLayout Panel, the rectangle is nowhere to be seen. Is there something different that needs to be done when adding graphics to a CardLayout panel?
The Main Class
import java.awt.CardLayout;
import java.awt.Container;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.JLabel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;
public class Window extends JFrame {
public Window() {
// Main Panel Configuration
Container panel = this.getContentPane();
panel.setLayout(new GridBagLayout());
panel.setSize(1000,1000);
GridBagConstraints gbc = new GridBagConstraints();
// GridBag Constraints
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridheight = 1;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridx = 0;
gbc.gridy = 0;
// Button Tabs
JButton button1 = new JButton("button 1");
panel.add(button1, gbc);
JButton button2 = new JButton("button 2");
gbc.gridx = 1;
panel.add(button2, gbc);
// Panels for CardLayout
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
// Set Layout of Panels
panel1.setLayout(new GridBagLayout());
panel2.setLayout(new GridBagLayout());
// Set Dimensions of Panels
panel1.setSize(new Dimension(900, 500));
panel2.setSize(new Dimension(900, 500));
// Labels for panels
JLabel label1 = new JLabel("label 1");
gbc.gridx = 1;
gbc.gridy = 2;
panel1.add(label1, gbc);
JLabel label2 = new JLabel("label 2");
gbc.gridy = 2;
panel2.add(label2, gbc);
// TextFields for Panels
JTextField textField1 = new JTextField();
gbc.gridx = 2;
gbc.gridy = 2;
panel1.add(textField1, gbc);
JTextField textField2 = new JTextField();
gbc.gridy = 2;
panel2.add(textField2, gbc);
// Add Graphic to panel1
JPanel drawingPanel = new JPanel();
DrawingComponent dc = new DrawingComponent();
dc.setPreferredSize(new Dimension(100, 100));
drawingPanel.add(dc);
gbc.gridx = 0;
gbc.gridy = 3;
panel1.add(drawingPanel,gbc);
// Set TextField Dimensions
textField1.setPreferredSize(new Dimension(400, 20));
textField2.setPreferredSize(new Dimension(400, 20));
// CardLayout Panel for Entry Fields and Labels
JPanel cardLayoutPanel = new JPanel();
CardLayout c1 = new CardLayout();
cardLayoutPanel.setLayout(c1);
cardLayoutPanel.setSize(new Dimension(900, 600));
// Add Panels to CardLayout Panel
cardLayoutPanel.add("panel1",panel1);
cardLayoutPanel.add("panel2", panel2);
// Which panel to show First
c1.show(cardLayoutPanel, "panel1");
// Add CardLayout Panel to Main Panel
gbc.gridy = 1;
gbc.gridx = 0;
panel.add(cardLayoutPanel, gbc);
// Action Listeners Changing Between Tabs
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
c1.show(cardLayoutPanel, "panel1");
}
});
button2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
c1.show(cardLayoutPanel, "panel2");
}
});
setSize(800,600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args){
Window window = new Window();
}
}
The Drawing Component Class
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.awt.Rectangle;
public class DrawingComponent extends JComponent {
public void paintComponent(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Rectangle rect1 = new Rectangle(400, 400, 50, 50);
g2.draw(rect1);
}
}
One problem is that you are drawing outside the bounds of your component. Drawing a rectangle at (400, 400) will result in nothing being seen, when the component itself is forced to have a size of 100×100.
Another problem is that you are trying to explicitly set the sizes of your components and your window. But the window is not big enough for those sizes. When GridBagLayout is unable to accommodate the preferred sizes of its children, it “gives up” and sets everything to its minimum size. Since DrawingComponent doesn’t define a minimum size, it reverts to having zero width and zero height. (Your use of fill=HORIZONTAL forces it to be as wide as its cell, but the height is still zero.)
It is not correct to set all those sizes. There is almost never a valid reason to call setSize or setPreferredSize.
For a JTextField, you need to set its size using its setColumns method.
The DrawingComponent class should know what size it wants to be, and it should return that size by overriding its own getPreferredSize method. Obviously it has to be large enough to accommodate its own painting:
@Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
For panels and windows, do not set the size at all. They will all be big enough to accommodate their child components, if you build the entire window and then call pack() on it.
Again, there should be no calls to setSize or setPreferredSize in your code. You don’t need them.