Search code examples
javaswingjpanelgraphics2d

Rectangles, shapes aren't showing up (Java/Swing) using multiple JPanels


I'm trying to make a program that can pretty much draw rectangles, shapes on the screen. So far I've made a GUI that has a menu bar and toolbar with some buttons (which aren't functioning yet).

Now I'm stuck with this problem that my rectangles aren't showing up on my drawing panel and I'm thinking it's due to JPanels who overlap on each other that my DrawRectangle class. But I'm not sure.

This is my DrawRectangle class where I wan't to draw rectangles and then put them in to my DrawingPanel (if that's possible).

package Shapes;

import java.awt.Graphics;

import javax.swing.JPanel;

public class DrawRectangle extends JPanel 
{
    private static final long serialVersionUID = 1L;

    public int old_x;
    public int old_y;
    public int new_x;
    public int new_y;

    public DrawRectangle(int old_x, int old_y, int new_x, int new_y)
    {
        this.old_x = old_x;
        this.old_y = old_y;
        this.new_x = new_x;
        this.new_y = new_y;

        repaint();
    }

    public void paintComponent(Graphics g)
    {
        g.drawRect(old_x, old_y, new_x, new_y);
    }
}

This is my DrawingPanel class where I would like to store all the painted graphics from my DrawRectangle class

package Panel;

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

import Shapes.DrawRectangle;

    public class DrawingPanel
    {   
        private JPanel drawPanel;

         private int tool = 1;
         int currentX, currentY, oldX, oldY;

        public DrawingPanel()
        {
            drawPanel = new JPanel();               
            drawPanel.setBackground(Color.WHITE);
            drawPanel.setBorder(BorderFactory.createLineBorder(Color.black));

            // Testing, neither of them are showing up (trying without mouse)
            new DrawRectangle(100,100,100,100); 
            new DrawRectangle(200,200,300,100); 

            drawPanel.addMouseListener(new MouseAdapter(){
                public void mousePressed(MouseEvent evt){
                    drawPanelMousePressed(evt);
                }

                public void mouseReleased(MouseEvent evt){
                    drawPanelMouseReleased(evt);
                }
            });

            drawPanel.addMouseMotionListener(new MouseMotionAdapter(){
                public void mouseDragged(MouseEvent evt){
                    drawPanelMouseDragged(evt);
                }
            });
        }

        public JPanel getDrawPanel() 
        {
            return drawPanel;
        }

        private void drawPanelMouseDragged(MouseEvent evt) {
            if (tool == 1) {
                currentX = evt.getX();
                currentY = evt.getY();
                oldX = currentX;
                oldY = currentY;
                System.out.println(currentX + " " + currentY);
                System.out.println("PEN!!!!");
            }
        }

        private void drawPanelMousePressed(MouseEvent evt) {
            oldX = evt.getX();
            oldY = evt.getY();
            System.out.println(oldX + " " + oldY);
        }


        private void drawPanelMouseReleased(MouseEvent evt) {
             currentX = evt.getX();
             currentY = evt.getY();

        }
    }

Also I'm considering my JPanel container that might be responsible for my DrawingPanel content not showing up. Here's my ContainerPanel class

package Panel;

import java.awt.BorderLayout;

import javax.swing.JPanel;

public class ContainerPanel
{
    private JPanel containerPanel;

    public ContainerPanel()
    {
        containerPanel = new JPanel(new BorderLayout());                                
        containerPanel.setOpaque(true);
        containerPanel.add(new DrawingPanel().getDrawPanel(), BorderLayout.CENTER);     
        containerPanel.add(new ToolBarPanel().getToolBarPanel(), BorderLayout.NORTH);   
    }

    public JPanel getContainerPanel()
    {
        return containerPanel;
    }
}

First time in stackoverflow :)


Solution

  • drawPanel = new JPanel();  
    

    When you create a panel, you assign it to a variable so you can use the variable in the getDrawPanel() method.

    new DrawRectangle(100,100,100,100); 
    

    Here you create a DrawRectangle but you don't do anything with it. You don't add it to the drawPanel or anything so it will never get painted.

    and I'm thinking it's due to JPanels who overlap on each other that my DrawRectangle class.

    Even if you fix the above problem and add your DrawRectangle class to the DrawPanel you will still have problems:

    1. A JPanel is opaque so the last painted panel will cover the bottom panel.
    2. Your DrawRectangle panel doesn't have a preferredSize since you didn't override the getPreferredSize() method so the size will be 0 so there is nothing to paint
    3. A JPanel uses a FlowLayout so each component will be positioned on the panel based on the rules of the layout manager, so your Rectangle will not paint at the location you think it should be.

    You need to start by reading the Swing Tutorial for Swing basics. Maybe section on:

    1. Custom Painting - will show you how to properly override the paintCompnent() method and implement a getPreferredSize() method

    2. Doing Without a Layout Manager - because you will want to place the components at a specific location (ie. the x/y of the Rectangle).

    Having said all that an easier solution to do custom painting of all the Rectangle on a single panel. Check out Custom Painting Approaches. It has working examples to demonstrate the two common ways to do this:

    1. Add object you want to paint to a List and then the painting method will iterate through the List to paint each object.
    2. Paint directly to a BufferedImage and then just paint the BufferedImage either by using a JLabel of by custom painting.