Anton Giertli
Anton Giertli

Reputation: 936

Forward event to all components JAVA

i dont how to solve this problem. I am developing a graphical editor, where arc(line) drawing is possible. I manually set the size of arc component to 1000x1000, so i dont have to change it when this arc will be dragged & dropped. Then i paint into this component the arc of the desired dimensions. Every arc components have mouse listener installed. The problem is, that only the most upper arc component get the mouse message. Also i have a mouse click listener installed on the JPane itself, but the mouse click listener on the most upper component simply gets all the events...It is kinda hard to describe this problem, so i will provide you with the simple image

enter image description here

So the first solution is to somehow forward the received message to the component that lies under, however i dont know how to do this, so do you have any ideas ?

The second solution is, not to set constant dimenstion to the arc object, but somehow rotate the rectangle in which that arc will be, i mean it like this. enter image description here

however, there still can be the overlapping problem.

So, do you have any ideas how to solve this problem ? or if you have any other ideas, how to solve this, id be happy, i simply need that the correct arc will react to the mouse click.

I dont think that the my code will somehow helps, but here it is

arcObject.setSize(1000, 1000); // !

and then, in this component i draw an arc

toX = o2.x - 24 * Math.cos(theta);
toY = o2.y - 24 * Math.sin(theta);
g2.draw(new Line2D.Double(toX, toY, o1.x, o1.y));

Upvotes: 1

Views: 2794

Answers (4)

pto3
pto3

Reputation: 521

I tried two ways to forvard events to several components. The first way is to redispatch events from a GlassPane to all components wich appears under it. The second way is to use global even listener AWTEventListener

Here is the code of the first way. Note if your GlassPane has other size as opposed to ContentPane you will need to convert coordinates of mouse cursor (I don't know but I thin the convertPoint(...) method is pertinent).

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

public class Test extends JFrame {
    public Test() {
        super();

        JButton testBtn = new JButton("Test");
        testBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Button's MouseEvent");
            }
        });
        add(testBtn, BorderLayout.SOUTH);

        ControlPanel control = new ControlPanel(getContentPane());
        setGlassPane(control);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200, 200);
        setVisible(true);
        control.setVisible(true);
    }

    private class ControlPanel extends JComponent {
        private Container underControl;

        public ControlPanel(Container underControl) {
            this.underControl = underControl;
            // Instead settig some listeners.
            // If any listeners doesn't set, any events will not process
            enableEvents(MouseEvent.MOUSE_EVENT_MASK);
            setOpaque(false);
        }

        @Override
        public void processMouseEvent(MouseEvent e) {
            // do something
            redispatchMouseEvent(e);
        }

        private void redispatchMouseEvent(MouseEvent e) {
            System.out.println("redispatchMouseEvent()");
            Component[] components = underControl.getComponents();
            for(Component c : components) {
                if(c.getBounds().contains(e.getX(), e.getY())) {
                    e = SwingUtilities.convertMouseEvent(underControl, e, c);
                    java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
                }
            }
        }
    }

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

And here is the second way.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.MouseInputAdapter;

public class Test extends JFrame {

    public Test() {
        super();

        JButton btn = new JButton("Test");
        btn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("JButton.onMouseClicked()");
            }
        });
        add(btn, "South");

        long eventMask = AWTEvent.MOUSE_MOTION_EVENT_MASK;
        Toolkit.getDefaultToolkit().addAWTEventListener(
            new AWTEventListener() {
                public void eventDispatched(AWTEvent e) {
                    System.out.println(e.getID());
                    if(e.getID() == MouseEvent.MOUSE_DRAGGED) {
                        System.out.println("Dragged");
                    }
                    if(e.getSource() instanceof JButton) {
                        System.out.println("Under the button");
                    }
                }
            },
        eventMask
        );

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(200, 200);
        setVisible(true);
    }

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

Upvotes: 1

Anton Giertli
Anton Giertli

Reputation: 936

I solved it like this:

  1. save all created arcs to the List
  2. when mouse clicked, loop through all the arcs
  3. create new Line2D object, with the parameters of the arc saved in the list, like this:

    Line2D line = new Line2D.Double(...)

  4. check this condition

    if (line.ptLineDist(x, y) < 3) { ... //we clicked on the line, do something

    }

Upvotes: 1

trashgod
trashgod

Reputation: 205875

You may be able to adapt the approach shown in GraphPanel. While the chosen implementation for List<Node> has a fixed order, a different implementation could allow commands such as Move Forward, Move Backward and Group.

Upvotes: 1

mKorbel
mKorbel

Reputation: 109823

did you mean redirect MouseEvents from one JComponent to the another?, for example

enter image description here

import javax.swing.*;
import java.awt.event.*;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Component;

public class SSCCE {

    private JFrame componentsFrame = new JFrame();
    private JFrame remoteFrame = new JFrame();
    private int lastMouseX, lastMouseY;
    final JPanel panel = new JPanel();

    public SSCCE() {
        panel.add(new JButton("A Button"));
        panel.add(new JComboBox(new String[]{"A", "Combo", "Box"}));
        panel.add(new JSlider());
        panel.add(new JList(new String[]{"A", "List"}));
        panel.add(new JCheckBox("Check Box"));
        componentsFrame.add(panel);
        componentsFrame.setGlassPane(new JPanel() {

            private static final long serialVersionUID = 1L;

            @Override
            public void paintComponent(Graphics g) {
                g.setColor(Color.red);
                g.drawLine(lastMouseX - 8, lastMouseY, lastMouseX + 8, lastMouseY);
                g.drawLine(lastMouseX, lastMouseY - 8, lastMouseX, lastMouseY + 8);
            }

            @Override
            public boolean isOpaque() {
                return false;
            }

            @Override
            public boolean isVisible() {
                return true;
            }
        });
        componentsFrame.setEnabled(false);
        componentsFrame.pack();
        componentsFrame.setVisible(true);
//        
        MouseAdapter mouseImpl = new MouseAdapter() {

            private Component lastPressed;

            @Override
            public void mousePressed(MouseEvent e) {
                redirectMouseEvent(e);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                redirectMouseEvent(e);
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                redirectMouseEvent(e);
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                redirectMouseEvent(e);
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                redirectMouseEvent(e);
            }

            private void redirectMouseEvent(MouseEvent e) {
                Component redirectTo = SwingUtilities.getDeepestComponentAt(panel, e.getX(), e.getY());
                if (e.getID() == MouseEvent.MOUSE_PRESSED) {
                    lastPressed = redirectTo;
                } else if (e.getID() == MouseEvent.MOUSE_DRAGGED || e.getID() == MouseEvent.MOUSE_RELEASED) {
                    redirectTo = lastPressed;
                }
                if (redirectTo != null) {
                    lastMouseX = e.getX();
                    lastMouseY = e.getY();
                    panel.repaint(); //this line is just to update the glass pane
                    e = SwingUtilities.convertMouseEvent(panel, e, redirectTo);
                    java.awt.Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
                }
            }
        };
        remoteFrame.getContentPane().addMouseListener(mouseImpl);
        remoteFrame.getContentPane().addMouseMotionListener(mouseImpl);
        remoteFrame.setSize(componentsFrame.getSize());
        remoteFrame.setLocation(0, componentsFrame.getY() + componentsFrame.getHeight());
        remoteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        remoteFrame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                SSCCE sSCCE = new SSCCE();
            }
        });
    }
}

Upvotes: 5

Related Questions