我有一个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
类,并拥有一个知道其内部的填充多边形/椭圆/圆形矩形。