arjacsoh
arjacsoh

Reputation: 9262

Listener invokes another listener

In a class which creates a menu using Swing I have added 4 items, each one of them is responsible for drawing a circle of different color. I have assigned to each item of that menu an ActionListener just to specify the color of the desired circle. I need following to click the mouse anywhere in the Panel and there the circle to be created. To this effect, I have created another class ScrollPane which implements the mouseListener and it is responsible to draw the circle. I do not know though, how to trigger the mouseListener to the second class which will do the job. This should be done only after the listener of the menu has been invoked. I need obviously a reference to class ScrollPane and then to assign on that the mouseListener.

I do not know however what kind of parameter I should use to the method addMouseListener. Or this is declared in ScrollPane class? I think it is simple in case all tasks are carried out in one class which implements both listeners, but what if I want to separate them?What else should the actionPerformed do? Here is the relevant code:

public class CreateMenu implements ActionListener {
    private ScrollPane scrollPane;

    public void actionPerformed(ActionEvent e) {
        JMenuItem source = (JMenuItem)(e.getSource());
        if(source.getText() == "Green Circle")
            this.scrollPane.setColor(Color.green);
         else if(source.getText() == "Blue Circle")
             this.scrollPane.setColor(Color.blue);
         else if(source.getText() == "Red Circle")
             this.scrollPane.setColor(Color.red);
         else if(source.getText() == "Yellow Circle")
             this.scrollPane.setColor(Color.yellow);
         else
             return;
     }
}

.

public class ScrollPane extends JPanel implements MouseListener {
    private Dimension area;
    private Vector<Circle> circles;
    private Color color;
    private JPanel drawingPane;

    public ScrollPane() {
        super(new BorderLayout());

        area = new Dimension(0,0);
        circles = new Vector<Circle>();

        //Set up the drawing area.
        drawingPane = new DrawingPane();
        drawingPane.setBackground(Color.white);
        drawingPane.addMouseListener(this);

        //Put the drawing area in a scroll pane.
        JScrollPane scroller = new JScrollPane(drawingPane);
        scroller.setPreferredSize(new Dimension(200,200));

        add(scroller, BorderLayout.CENTER);
    }

    public class DrawingPane extends JPanel {
        protected void paintComponent(Graphics g, Color color ) {
            super.paintComponent(g);

            Rectangle rect;
            for (int i = 0; i < circles.size(); i++) {
                rect = circles.elementAt(i).getRect();
                g.setColor(circles.elementAt(i).getTheColor());
                g.fillOval(rect.x, rect.y, rect.width, rect.height);
            }
        }
    }

    public void mouseReleased(MouseEvent e) {
        final int W = 100;
        final int H = 100;
        boolean changed = false;

        if(SwingUtilities.isLeftMouseButton(e)) {
            int x = e.getX() - W/2;
            int y = e.getY() - H/2;
            if (x < 0) x = 0;
            if (y < 0) y = 0;
            Rectangle rect = new Rectangle(x, y, W, H);
            Circle newCircle = new Circle(rect, this.color);
            circles.addElement(newCircle);
            drawingPane.scrollRectToVisible(rect);

            int this_width = (x + W + 2);
            if (this_width > area.width) {
                area.width = this_width; changed=true;
            }

            int this_height = (y + H + 2);
            if (this_height > area.height) {
                area.height = this_height; changed=true;
            }
        }
        if (changed) {
            //Update client's preferred size because
            //the area taken up by the graphics has
            //gotten larger or smaller (if cleared).
            drawingPane.setPreferredSize(area);

            //Let the scroll pane know to update itself
            //and its scrollbars.
            drawingPane.revalidate();
        }
        drawingPane.repaint();
    }
    public void mouseClicked(MouseEvent e){}
    public void mouseEntered(MouseEvent e){}
    public void mouseExited(MouseEvent e){}
    public void mousePressed(MouseEvent e){}


    public void setColor(Color color) {
        this.color = color;
    }

    public JPanel getDrawingPane() {
        return drawingPane;
    }
}

Upvotes: 2

Views: 1922

Answers (2)

trashgod
trashgod

Reputation: 205885

You can always forward events from one component to another, as shown here; and Action is the preferred way to encapsulate behavior shared by menus and components.

In this case, it looks like you want to do the drawing and mouse handling yourself. You might like to examine this simple GraphPanel, which relies on common listeners instead.

Upvotes: 1

Marvo
Marvo

Reputation: 18143

Don't try to resend a mouse-listener call, if that's what you're trying to do. You're not a mouse. Instead, have the mouse listener methods simply call other methods on your objects that do the actual work. Your mouse listener routines should be trivial "If this, call this, if that, call that."

Then, if there's a relationship between objects, let one of them receive the mouse listener clicks. Then invoke the methods on all objects that should be affected by that click.

What I've done in the past when, say, a grid is placed inside another swing object, is to create my own listener patterns. Then, when something happens to object X that needs to be passed along to object Y, I use my listener pattern. That way, it's clear what work needs to be done whenever a given method is called. AND it's more reusable. So if it's not a mouse click but a menu that triggers something, I don't have to duplicate logic.

Sorry if that's not very clear.

Upvotes: 2

Related Questions