Search code examples
javaswingkeylistenerpaintcomponent

How do I set a color for g.setColor(); when drawing circles using a KeyListener?


I have code which will draw circles depending on where the user clicks, and then will draw lines connecting those circles. I want to have the color of the circles and lines be set as Black by default, but the user can type either r,b,g,l (red, blue,green,black) to set the color of the NEXT circle and lines being drawn. What would I have to put inside of my KeyTyped method? I have if/else statements set up for whenever the user enters r,b,g, or l.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Circle extends JPanel implements MouseListener, KeyListener, MouseMotionListener {

    private List<Point> points;

    public static void main(String[] args) {

        EventQueue.invokeLater(() -> new Circle().buildAndDisplayGui());
    }

    public Circle() {
        points = new ArrayList<>();
        setPreferredSize(new Dimension(500, 500));
        setBackground(Color.white);
        addMouseListener(this);
    }

    private void buildAndDisplayGui() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        frame.addKeyListener(this);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.black);
        int count = points.size();
        for (int i = 0; i < count; i++) {
            Point pt0 = points.get(i);
            g.fillOval(pt0.x - 10, pt0.y - 11, 20, 20);
            if (i > 0) {
                Point pt1 = points.get(i - 1);
                g.drawLine(pt1.x, pt1.y, pt0.x, pt0.y);
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        //Prints the coordinates of the clicks
        System.out.println("X: " + e.getX() + "  Y: " + e.getY());
        Point pt = new Point(e.getX(), e.getY());
        points.add(pt);
        repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // Do nothing.
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // Do nothing.
    }

    @Override
    public void mousePressed(MouseEvent e) {
        // Do nothing.
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // Do nothing.
    }

    @Override
    public void mouseDragged(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    @Override
        public void keyTyped(KeyEvent e) {
    
     if (e.getKeyChar() == 'r') { 
         
        //Sets the color of the next circle and lines to red
    
        } else {
      
            if (e.getKeyChar() == 'b') { 
                
                //Sets the color of the next circle and lines to blue
      
                } else {
      
                    if (e.getKeyChar() == 'g') { 
                        
                        //Sets the color of the next circle and lines to green
      
                        } else {
      
                            if (e.getKeyChar() == 'l') { 
                                
                                //Sets the color of the next circle and lines to black
                            
                            } 
                        } 
                    } 
                } 
            }
     

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub

    }
}

Current output:

enter image description here

Desired Output (If the user presses “r” after two mouse clicks and the does two more mouse clicks):

enter image description here


Solution

    1. Add a Color instance variable to class Circle. In the example, I called it "currentColor". I set it to Color.black in the constructor.

    2. Save a Color with each item in points. One way to do that is to have a parallel array. I don't like tightly coupled arrays, so I created a helper class in my example.

    class PointAndColor { 
         Point thePoint;
         Color theColor;
         PointAndColor () { 
             theColor = Color.black;
             thePoint = new Point (0,0);            
         }
            
         PointAndColor (Point point, Color color) { 
              theColor = color;
              thePoint = point;
         }
            
         Color getColor () { return theColor; }
         Point getPoint () { return thePoint; }
     }
    
    

    I changed the generic type of the List of Points:

      private List<PointAndColor> points;
      private Color currentColor;
    

    Example of saving the color with the point:

    @Override
    public void mouseClicked(MouseEvent e) {
        //Prints the coordinates of the clicks
        System.out.println("X: " + e.getX() + "  Y: " + e.getY());
        Point pt = new Point(e.getX(), e.getY());
        points.add (new PointAndColor (pt, currentColor));
        repaint();
    }
    
    1. Set the current color in the keyTyped method

      @Override
       public void keyTyped(KeyEvent e) {           
      
          switch (e.getKeyChar()) {
              case 'r':
                  currentColor = Color.red;
                  break;
      
              case 'g':
                  currentColor = Color.green;
                  break;
      
              case 'b':
                  currentColor = Color.blue;
                 break;
      
              case 'l':
                  currentColor = Color.black;
                  break;
      
              default:
                  break;
       }
       System.out.println ("Color set to " + currentColor);
      

      }

    2. Retrieve the Color with the Point:

         
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int count = points.size();
            for (int i = 0; i < count; i++) {
                Point pt0 = points.get(i).getPoint();
                g.setColor (points.get(i).getColor());
                g.fillOval(pt0.x - 10, pt0.y - 11, 20, 20);
                if (i > 0) {
                    Point pt1 = points.get(i - 1).getPoint();
                    g.drawLine(pt1.x, pt1.y, pt0.x, pt0.y);
                }
            }
        }