java 单击绘制的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12933592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clicking on a drawn object
提问by Dot NET
I've got a class called Shape
which inherits from JPanel.
我有一个Shape
继承自 JPanel 的类。
A number of sub-classes in turn extend the Shape
classes, one for each type of shape.
许多子类依次扩展了这些Shape
类,每种形状都有一个。
Each shape has its own overriden paint()
method, which draws the respective shape.
每个形状都有自己的覆盖paint()
方法,用于绘制相应的形状。
I would like to be able to click on any shape, and am trying to implement this logic for now. Please note that each shape has been added to an arrayList.
我希望能够点击任何形状,现在我正在尝试实现这个逻辑。请注意,每个形状都已添加到一个数组列表中。
However, the contains statement always returns false, even when I have clearly clicked inside the shape.
但是,包含语句总是返回 false,即使我已经清楚地单击了形状内部。
Any ideas?
有任何想法吗?
回答by David Kroukamp
Never override paint()
in JPanel
rather paintComponent(..)
永不覆盖paint()
在JPanel
相当paintComponent(..)
Im not quite sure I understand however I made a short example which I hope will help.
Basically it is a simple JFrame
with a DrawingPanel
(my own class which extends JPanel
and the shapes are drawn on). This panel will create shapes (only 2 for testing) add them to an ArrayList
and draw them to the JPanel
via paintComponent(..)
and a for
loop, it also has a MouseAdapter
to check for user mouseClicked(..)
evnets on the JPanel
. When a click is made we iterate through each Shape
in the ArrayList
and check whether the Shape
contains the point or not, and if so prints its class name and uses instance of
to check what type of Shape
is clicked and prints appropriate message:
我不太确定我理解但我做了一个简短的例子,我希望会有所帮助。基本上它是一个简单JFrame
的DrawingPanel
(我自己的类,它扩展JPanel
并绘制了形状)。本专题将创建形状(只有2个用于测试)将它们添加到一个ArrayList
和借鉴他们的JPanel
通过paintComponent(..)
和一个for
循环,它也有一个MouseAdapter
检查用户mouseClicked(..)
的evnets JPanel
。当点击由我们迭代通过每个Shape
在ArrayList
和检查是否Shape
包含点或不是,如果是打印它的类名和用途instance of
检查什么类型的Shape
被点击并打印相应的消息:
Output(after clicking both shapes):
输出(点击两个形状后):
Clicked a java.awt.geom.Rectangle2D$Double
Clicked a rectangle
Clicked a java.awt.geom.Ellipse2D$Double
Clicked a circle
单击一个 java.awt.geom.Rectangle2D$Double
单击一个矩形
单击一个 java.awt.geom.Ellipse2D$Double
点击了一个圆圈
ShapeClicker.java:
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;
}
}
回答by John Dvorak
If you are implementing Shape
you have to implement the contains
method yourself. The default implementation for Shape
always returns false
.
如果您正在实施Shape
,则必须自己实施该contains
方法。Shape
始终返回的默认实现false
。
If your Shape
is bounded by curves that you know how to intersect (or determine if a point is on one or the other side), you can use the even-odd rule. Cast a ray from the point tested in any direction not parallel to a straight line. If the number of intersections is odd, the point is inside. If the number of intersections is even, the point is outside.
如果您Shape
的边界是您知道如何相交的曲线(或确定一个点是在一侧还是另一侧),则可以使用奇偶规则。从不平行于直线的任何方向从测试点投射一条射线。如果交点数为奇数,则该点在里面。如果交叉点的数量是偶数,则该点在外面。
The built-in classes implement this method, so you can use/extend the Polygon
, Ellipse2D.Double
or RoundRectangle2D.Double
class and have a filled polygon / ellipse / round rectangle that knows its inside.
内置类实现了此方法,因此您可以使用/扩展Polygon
,Ellipse2D.Double
或RoundRectangle2D.Double
类并拥有一个知道其内部的填充多边形/椭圆/圆角矩形。