0

I am having a problem with my code where the left menu bar is being duplicated whenever I draw something in my program. When a shape gets created, it repaints the panel but is also painting the left menu bar into the panel, as you can paint over it with a new shape and it gets covered and isn't functional. I'm not sure what is causing this, but the painting panel should also have it's background color set to Cyan which isn't happening.

Upon opening

After drawing

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main extends JFrame implements ActionListener {
    DrawPanel centerPanel;
    
    public static void main(String[] args) {
        Main main = new Main();
        main.setSize(500,500);
        main.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        main.setVisible(true);
    }
    
    public Main() {
        super("My Paint App");
        // South
        JPanel southPanel = new JPanel();
        southPanel.setBackground(Color.BLACK);
        JButton b1 = new JButton("Undo");
        JButton b2 = new JButton("Erase");
        southPanel.add(b1);
        southPanel.add(b2);
        // West
        JPanel westPanel = new JPanel();
        westPanel.setBackground(Color.BLACK);
        String[] colors = {"Black", "Red", "Blue", "Green", "Yellow", "Orange", "Pink"};
        JComboBox<String> list = new JComboBox<String>(colors);
        JRadioButton rectangle = new JRadioButton("Rectangle");
        JRadioButton circle = new JRadioButton("Circle");
        JRadioButton arc = new JRadioButton("Arc");
        rectangle.setSelected(true);
        ButtonGroup group = new ButtonGroup();
        group.add(rectangle);
        group.add(circle);
        group.add(arc);
        GridLayout grid = new GridLayout(7,1);
        westPanel.setLayout(grid);
        westPanel.add(list);
        westPanel.add(rectangle);
        westPanel.add(circle);
        westPanel.add(arc);
        // Center
        centerPanel = new DrawPanel();
        centerPanel.setBackground(Color.CYAN);
        // Frame
        BorderLayout layout = new BorderLayout();
        setLayout(layout);
        add(southPanel, BorderLayout.SOUTH);
        add(westPanel, BorderLayout.WEST);
        add(centerPanel, BorderLayout.CENTER);
        // Listeners
        list.addActionListener(this);
        rectangle.addActionListener(this);
        circle.addActionListener(this);
        arc.addActionListener(this);
        b1.addActionListener(this);
        b2.addActionListener(this);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println(e.getActionCommand());
        //** If color combo box is changed, updates what color to draw with
        if (e.getActionCommand().equals("comboBoxChanged")) {
            JComboBox tmp = (JComboBox) e.getSource();
            Object selection = tmp.getSelectedItem();
            System.out.println(selection);
            if (selection.equals("Black"))
                centerPanel.setColor(Color.BLACK);
            else if (selection.equals("Red"))
                centerPanel.setColor(Color.RED);
            else if (selection.equals("Blue"))
                centerPanel.setColor(Color.BLUE);
            else if (selection.equals("Green"))
                centerPanel.setColor(Color.GREEN);
            else if (selection.equals("Yellow"))
                centerPanel.setColor(Color.YELLOW);
            else if (selection.equals("Orange"))
                centerPanel.setColor(Color.ORANGE);
            else if (selection.equals("Pink"))
                centerPanel.setColor(Color.PINK);
        }
        //** If shape radio buttons are changed, updates what shape to draw
        if (e.getActionCommand().equals("Rectangle"))
            centerPanel.setShape("rectangle");
        else if (e.getActionCommand().equals("Circle"))
            centerPanel.setShape("circle");
        else if (e.getActionCommand().equals("Arc"))
            centerPanel.setShape("arc");
    }

}
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

public class DrawPanel extends JPanel implements MouseListener, MouseMotionListener {
    int x1, y1, x2, y2;
    Color color = Color.BLACK;
    String shape = "rectangle";
    
    public DrawPanel() {
        addMouseListener(this);
        addMouseMotionListener(this);
    }
    
    public void paintComponent (Graphics g) {
        g.setColor(color);
        if (shape.equals("rectangle"))
            g.fillRect(x1, y1, x2-x1, y2-y1);
        else if (shape.equals("circle"))
            g.fillOval(x1, y1, x2-x1, y2-y1);
        else if (shape.equals("arc"))
            g.fillArc(x1, y1, y2, y1, x2, x1);
    }
    
    public void mousePressed(MouseEvent e) {
        x1 = e.getX();
        y1 = e.getY();
    }
    
    public void mouseReleased(MouseEvent e) {
        x2 = e.getX();
        y2 = e.getY();
        System.out.println(x1 + ", " + y1 + ", " + x2 + ", " + y2);
        repaint();
    }
    
    public void setColor(Color color) {
        this.color = color;
    }
    
    public void setShape(String shape) {
        this.shape = shape;
    }
    
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseDragged(MouseEvent e) {}
    public void mouseMoved(MouseEvent e) {}
}
Mr. Goose
  • 55
  • 7
  • 3
    Your `paintComponent` method override does not appear to be calling the super's method, and this will break the painting chain. You really should call `super.paintComponent(g);` within your own override method, often as the first call of the method, so that Swing can do its own house-keeping painting, including removing "dirty" pixels from the window. – DontKnowMuchBut Getting Better Nov 25 '21 at 19:10
  • Please look at the detailed answer provided by MadProgrammer in [this similar question and answer](https://stackoverflow.com/a/13281121/7210739) to see more about this issue. – DontKnowMuchBut Getting Better Nov 25 '21 at 19:13
  • Thanks, that's exactly what I needed. – Mr. Goose Nov 25 '21 at 19:18
  • Yay! Glad that you've got it working! – DontKnowMuchBut Getting Better Nov 25 '21 at 19:20
  • 1
    the [documentation](https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)) of `paintComonent` says *"if you do not invoke super's implementation you must honor the opaque property, that is if this component is opaque, you must completely fill in the background in an opaque color. If you do not honor the opaque property you will likely see visual artifacts."* – user16320675 Nov 25 '21 at 19:40

0 Answers0