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
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();
}
}
I solved it like this:
create new Line2D object, with the parameters of the arc saved in the list, like this:
Line2D line = new Line2D.Double(...)
check this condition
if (line.ptLineDist(x, y) < 3) { ... //we clicked on the line, do something
}
did you mean redirect MouseEvents from one JComponent to the another?, for example
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();
}
});
}
}
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
.