Dragon-Ash
Dragon-Ash

Reputation: 71

How to update (more than one?) JPanel on mouse click?

I have a JFrame, comprised of three JPanel containers, each panel has a filled-in circle (for example, red, white blue).

What I'd like to be able to do is update the color of the filled-in circle of that panel (make it darker with Color.RED.darker, for example) when that particular panel is clicked

I can't use an ActionListener, since panels aren't components but containers. I started out using MouseListener, but have now updated this to MouseAdapter. I am able to determine which JPanel was clicked - for testing purposes I'm printing out which panel was clicked to the console (for simplicity purposes I added a name to each panel).

EDIT: I got this mostly working - I can now repaint() the Jpanel that was clicked, making that cricle color darker, using the suggestion below of creating a setCircleColor (color) method, which calls repaint().This redraws the circle in that panel, using a darker color.

However, what I really also need to do is make the other two (non-clicked) cirlces on the other panels to repaint() with lighter colors.

But I can't see an easy way to handle this - how can I manipulate the other Jpanels that I didn't click on?

Here's my code:

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;


public class TrafficLight {

    // sets up the frame, calls the circle panels and adds them to the frame
    public static void setUpGui() {
        JFrame frame = new JFrame("Traffic Lights");
        frame.setSize(300, 900);
        frame.setLayout(new GridLayout(3, 0));


        DrawCirclePanel redCircle = new DrawCirclePanel(Color.RED);
        DrawCirclePanel yellowCircle = new DrawCirclePanel(Color.YELLOW);
        DrawCirclePanel greenCircle = new DrawCirclePanel(Color.GREEN);

        redCircle.setName("redCircle");
        yellowCircle.setName("yellowCircle");
        greenCircle.setName("greenCircle");

        CircleListener cl = new CircleListener();

        redCircle.addMouseListener(cl);
        yellowCircle.addMouseListener(cl);
        greenCircle.addMouseListener(cl);

        frame.add(redCircle);
        frame.add(yellowCircle);
        frame.add(greenCircle);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        setUpGui();
    }
}

// the DrawCirclePanel class creates a panel and
// draws a filled-in circle on the panel
class DrawCirclePanel extends JPanel {
    Color c;
    Border blackline = BorderFactory.createLineBorder(Color.black);

    // constructor for panel, takes Color as argument
    // so we know what color circle to make
    public DrawCirclePanel(Color color) {

        this.c = color;
        this.setLayout(new GridLayout(1, 0));
        this.setBorder(blackline);
    }

    // draws the circle in the panel
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int xWidth = this.getParent().getWidth();
        g.setColor(c);
        g.fillOval(1, 1, xWidth-1, xWidth-1);
    }

    public void setCircleColor(Color color) {
        this.c = color;
        this.getGraphics().setColor(c);
        this.repaint();
    }
}


class CircleListener extends MouseAdapter {

    public void mouseClicked(MouseEvent e) {
        DrawCirclePanel cPanel = (DrawCirclePanel) e.getSource();
        System.out.println(cPanel);
        String name = cPanel.getName();
        if (name == "redCircle") {
            cPanel.setCircleColor(Color.red.darker());
        }
        else if (name == "yellowCircle") {
            cPanel.setCircleColor(Color.yellow.darker());
        }
        else {
            cPanel.setCircleColor(Color.green.darker());
        }
    }
}

Upvotes: 0

Views: 316

Answers (1)

Dragon-Ash
Dragon-Ash

Reputation: 71

So the answer turned out to be fairly simple. Declare the panels with the circles as static variables so that the MouseListener class can access all three of the panels.

As Andrew Thompson noted, set up a setCircleColor method in DrawCirclePanel that repaints the circle with a different color as needed.

In the MouseListener class, determine with panel was called, then repaint all three of the circles, passing in the correct color - darker() or brighter() - as needed.

Here's the final code

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.Color;
import java.awt.event.*;
import java.awt.event.MouseEvent;


public class TrafficLight {

    static DrawCirclePanel redCircle;
    static DrawCirclePanel yellowCircle;
    static DrawCirclePanel greenCircle;


    // sets up the frame, calls the circle panels and adds them to the frame
    public static void setUpGui() {
        JFrame frame = new JFrame("Traffic Lights");
        frame.setSize(300, 900);
        frame.setLayout(new GridLayout(3, 0));

        redCircle = new DrawCirclePanel(Color.RED.brighter().brighter());
        yellowCircle = new DrawCirclePanel(Color.YELLOW.darker().darker());
        greenCircle = new DrawCirclePanel(Color.GREEN.darker().darker());

        redCircle.setName("redCircle");
        yellowCircle.setName("yellowCircle");
        greenCircle.setName("greenCircle");

        CircleListener cl = new CircleListener();

        redCircle.addMouseListener(cl);
        yellowCircle.addMouseListener(cl);
        greenCircle.addMouseListener(cl);

        frame.add(redCircle);
        frame.add(yellowCircle);
        frame.add(greenCircle);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        setUpGui();
    }
}


// the DrawCirclePanel class creates a panel and
// draws a filled-in circle on the panel
class DrawCirclePanel extends JPanel {
    Color c;
    Border blackLine = BorderFactory.createLineBorder(Color.BLACK);

    // constructor for panel, takes Color as argument
    // so we know what color circle to make
    public DrawCirclePanel(Color color) {
        this.c = color;
        this.setLayout(new GridLayout(1, 0));
        this.setBorder(blackLine);
    }

    // draws the circle in the panel
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        int xWidth = this.getParent().getWidth();
        g.setColor(c);
        g.fillOval(0, 0, xWidth, xWidth);
    }

    // changes the color and calls repaint after a mouseClicked event
    public void setCircleColor(Color color) {
        this.c = color;
        this.getGraphics().setColor(c);
        this.repaint();
    }
}

//abstract adapter class for receiving mouse events
class CircleListener extends MouseAdapter {

    // determine which panel was clicked; redraws as brighter circle
    // redraws other circles with dimmer (darker) color
    public void mouseClicked(MouseEvent e) {
        DrawCirclePanel cPanel = (DrawCirclePanel) e.getSource();
        String name = cPanel.getName();
        if (name.equals("redCircle")) {
            TrafficLight.redCircle.setCircleColor(Color.RED.brighter().brighter());
            TrafficLight.yellowCircle.setCircleColor(Color.YELLOW.darker().darker());
            TrafficLight.greenCircle.setCircleColor(Color.GREEN.darker().darker());
        } else if (name.equals("yellowCircle")) {
            TrafficLight.redCircle.setCircleColor(Color.RED.darker().darker());
            TrafficLight.yellowCircle.setCircleColor(Color.YELLOW.brighter().brighter());
            TrafficLight.greenCircle.setCircleColor(Color.GREEN.darker().darker());
        } else {
            TrafficLight.redCircle.setCircleColor(Color.RED.darker().darker());
            TrafficLight.yellowCircle.setCircleColor(Color.YELLOW.darker().darker());
            TrafficLight.greenCircle.setCircleColor(Color.GREEN.brighter().brighter());
        }
    }
}

Upvotes: 0

Related Questions