我有一个Shape继承自 JPanel 的类。
许多子类依次扩展了这些Shape类,一种用于每种形状。
每个形状都有自己的覆盖paint()方法,用于绘制相应的形状。
我希望能够单击任何形状,并且现在正在尝试实现此逻辑。请注意,每个形状都已添加到 arrayList。
但是,包含语句总是返回 false,即使我已经清楚地单击了形状内部。
有任何想法吗?
我有一个Shape继承自 JPanel 的类。
许多子类依次扩展了这些Shape类,一种用于每种形状。
每个形状都有自己的覆盖paint()方法,用于绘制相应的形状。
我希望能够单击任何形状,并且现在正在尝试实现此逻辑。请注意,每个形状都已添加到 arrayList。
但是,包含语句总是返回 false,即使我已经清楚地单击了形状内部。
有任何想法吗?
永远不要覆盖paint()而JPanel不是paintComponent(..)
我不太确定我是否理解,但是我做了一个简短的示例,希望对您有所帮助。基本上它是一个简单JFrame的DrawingPanel(我自己的类扩展JPanel并绘制形状)。此面板将创建形状(仅 2 个用于测试)将它们添加到一个ArrayList并将它们绘制到JPanel通孔paintComponent(..)和一个for循环,它还有一个MouseAdapter用于mouseClicked(..)检查JPanel. 当单击时,我们遍历每个Shape中的ArrayList并检查是否Shape包含该点,如果是,则打印其类名并用于instance of检查Shape单击的类型并打印适当的消息:

输出(单击两个形状后):
单击了 java.awt.geom.Rectangle2D$Double
单击了一个矩形
单击了 java.awt.geom.Ellipse2D$Double
点击了一个圈子
ShapeClicker.java:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ShapeClicker {
public ShapeClicker() {
JFrame frame = new JFrame();
frame.setTitle("Shape Clicker");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
initComponents(frame);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//create frame and components on EDT
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new ShapeClicker();
}
});
}
private void initComponents(JFrame frame) {
frame.add(new ShapePanel());
}
}
//custom panel
class ShapePanel extends JPanel {
private Shape rect = new Rectangle2D.Double(50, 100, 200, 100);
private Shape cirlce = new Ellipse2D.Double(260, 100, 100, 100);
private Dimension dim = new Dimension(450, 300);
private final ArrayList<Shape> shapes;
public ShapePanel() {
shapes = new ArrayList<>();
shapes.add(rect);
shapes.add(cirlce);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent me) {
super.mouseClicked(me);
for (Shape s : shapes) {
if (s.contains(me.getPoint())) {//check if mouse is clicked within shape
//we can either just print out the object class name
System.out.println("Clicked a "+s.getClass().getName());
//or check the shape class we are dealing with using instance of with nested if
if (s instanceof Rectangle2D) {
System.out.println("Clicked a rectangle");
} else if (s instanceof Ellipse2D) {
System.out.println("Clicked a circle");
}
}
}
}
});
}
@Override
protected void paintComponent(Graphics grphcs) {
super.paintComponent(grphcs);
Graphics2D g2d = (Graphics2D) grphcs;
for (Shape s : shapes) {
g2d.draw(s);
}
}
@Override
public Dimension getPreferredSize() {
return dim;
}
}
如果您正在实施Shape,则必须自己实施该contains方法。Shape总是返回的默认实现false。
如果您Shape的边界是您知道如何相交的曲线(或确定一个点是否在一侧或另一侧),您可以使用奇偶规则。从测试点向任何不平行于直线的方向投射光线。如果交叉点的数量是奇数,则该点在内部。如果交叉点的数量是偶数,则该点在外部。
内置类实现了此方法,因此您可以使用/扩展Polygon,Ellipse2D.Double或RoundRectangle2D.Double类,并拥有一个知道其内部的填充多边形/椭圆/圆形矩形。