我不知道如何解决这个问题。我正在开发一个图形编辑器,可以绘制弧线(线)。我手动将弧组件的大小设置为1000x1000,所以当这个弧被拖动时我不必改变它。下降。然后我在这个组件中绘制所需尺寸的弧。每个弧组件都安装了鼠标侦听器。问题是,只有最上面的弧组件才能获得鼠标消息。 此外,我在JPane本身上安装了一个鼠标点击监听器,但最上层组件上的鼠标点击监听器只是获取所有事件......有点难以描述这个问题,所以我将为您提供简单的图像< / p>
所以第一个解决方案是以某种方式将收到的消息转发给下面的组件,但我不知道该怎么做,所以你有什么想法吗?
第二个解决方案是,不是为弧对象设置常量尺寸,而是以某种方式旋转该弧将成为的矩形,我的意思是这样的。
但是,仍然存在重叠问题。那么,您对如何解决这个问题有什么想法吗?或者如果您有任何其他想法,如何解决这个问题,我很高兴,我只需要正确的弧线对鼠标点击做出反应。
我不认为我的代码会以某种方式帮助,但这里是
arcObject.setSize(1000, 1000); // !
然后,在这个组件中我画一个弧
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));
答案 0 :(得分:4)
你的意思是将MouseEvents从一个JComponent重定向到另一个JComponent,例如
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();
}
});
}
}
答案 1 :(得分:1)
您可以调整GraphPanel
中显示的方法。虽然List<Node>
选择的实施具有固定顺序,但不同的实施可以允许Move Forward
,Move Backward
和Group
等命令。
答案 2 :(得分:1)
创建新的Line2D对象,并将弧的参数保存在列表中,如下所示:
Line2D line = new Line2D.Double(...)
检查此情况
if(line.ptLineDist(x,y)&lt; 3){ ... //我们点击了这一行,做了一些事情
}
答案 3 :(得分:0)
我尝试了两种方法将事件转发给多个组件。第一种方法是将事件从GlassPane
重新发送到其下的所有组件。第二种方法是使用全局偶数监听器AWTEventListener
这是第一种方式的代码。请注意,如果您的GlassPane
具有其他尺寸而不是ContentPane
,则需要转换鼠标光标的坐标(我不知道,但我认为convertPoint(...)
方法是相关的)。
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();
}
}
这是第二种方式。
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();
}
}