Hello people,
你好,
I am trying to write an animated character for a multitouch screen. I want my object to have 5 eyes and each of whose pupil to be dragged and dropped differently, within the eye of course.
我正在为多点触控屏幕写一个动画角色。我想要我的物体有5只眼睛,每只眼睛的瞳孔都被不同的拖动和落下,当然是在眼睛里。
I have tried to do it all in a single class and the problem seems to be assigning mouse handlers to each of the five pupils! In other words, if I move one pupil, all the pupils are moving.
我试着在一个班级里做所有的事情,问题似乎是给五个学生分配鼠标处理器!换句话说,如果我移动一个学生,所有的学生都在移动。
Then, I resorted to using a bespoke class just to the pupil. When I use it by itself, the pupil is draggable. However, when I use it as an object in the eyes class, the pupil is static! No clicks registered, no mouse activity tracked.
然后,我只给学生上了预约课程。当我自己使用它时,瞳孔是可拖动的。然而,当我把它作为一个对象在眼睛课堂上时,瞳孔是静止的!没有点击注册,没有鼠标活动跟踪。
I have looked at tutorials, other related issues with mouse handlers and could not make any progress. I changed the code a dozen times from various tutorials and suggestions before finally posting here. Any ideas where I am missing the cue? Any pointers would be greatly appreciated.
我查看了教程,以及鼠标处理程序的其他相关问题,但没有取得任何进展。在最终发布到这里之前,我从各种教程和建议中修改了十几次代码。你知道我哪里漏了线索吗?如有任何建议,我们将不胜感激。
Thanks in advance.
提前谢谢。
PS: I know I am yet to put the constraints on the pupil movement within the eye.
PS:我知道我还没有限制瞳孔在眼睛里的运动。
Code for main eyes class:
主眼类代码:
package rollEyes;
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FiveEyes extends JPanel
{
private static final long serialVersionUID = 1L;
private static final int SIZE = 512;
private int a = SIZE / 2;
private int b = a;
private int r = 4 * SIZE / 5;
private int n;
int circleSize=30;
Pupil dc = new Pupil(1);
public FiveEyes(int n)
{
super(true);
this.setPreferredSize(new Dimension(SIZE, SIZE));
this.n = n;
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
a = getWidth() / 2;
b = getHeight() / 2;
int m = Math.min(a, b);
r = 4 * m / 5;
int r2 = Math.abs(m - r) / 2;
int numOfEyes = 5;
for (int i = 0; i < numOfEyes ; i++)
{
Graphics2D g2d2 = (Graphics2D) g;
double t = 2 * Math.PI * i / n;
int x = (int) Math.round(a + r * Math.cos(t));
int y = (int) Math.round(b + r * Math.sin(t));
drawEyeSockets(g2d2, x,y, 2*r2,2*r2);
}
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
create();
}
});
}
public void drawEyeSockets(final Graphics2D g2, int x, int y, int w, int h)
{
g2.drawOval(x,y,w,h);
dc.drawCircle(g2, x+12, y+12);
}
private static void create()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
FiveEyes fivey = new FiveEyes(5);
f.add(fivey);
f.pack();
f.setVisible(true);
}
}
Code for the Pupil class:
小学生班代码:
package rollEyes;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Pupil extends JPanel
{
private static final long serialVersionUID = 1L;
int radius=50;
int x_after = 50;
int y_after = 50;
MouseHandler mh ;
private static int n =1;
public Pupil(int n)
{
super(true);
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
drawCircle(g2d,x_after,y_after);
}
public void drawCircle(final Graphics2D g2d, int x, int y)
{
g2d.setColor(Color.BLUE);
g2d.fillOval(x, y, radius/2, radius/2);
mh = new MouseHandler();
this.addMouseListener(mh);
this.addMouseMotionListener(mh);
}
private static void create()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Pupil dc = new Pupil(n);
f.add(dc);
f.pack();
f.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
create();
}
});
}
private class MouseHandler extends MouseAdapter
{
boolean circleClicked=false;
public void mouseReleased(MouseEvent e)
{
circleClicked = false;
}
public void mousePressed(MouseEvent me)
{
circleClicked = true;
}
public void mouseDragged(MouseEvent me)
{
if (circleClicked)
{
x_after = me.getX();
y_after = me.getY();
repaint();
}
}
}
}
2 个解决方案
#1
3
You have Pupil extend JPanel, but really shouldn't be doing that. Instead, use the concepts that you've learned in your current Pupil class -- how to draw a movable circle, and extend it in the larger FiveEyes class, only this time create a List<Pupil>
and draw them. My suggestions:
你有瞳孔扩展JPanel,但真的不应该这么做。相反,使用你在当前的学生课程中学到的概念——如何绘制一个可移动的圆圈,并在较大的五眼课程中扩展它,只是这一次创建一个列表 <瞳孔> 并绘制它们。我的建议:
- Make Pupil not extend JPanel. Instead give it the machinery to draw circles in certain locations and to have that location changed.
- 使瞳孔不延伸JPanel。相反,给它一些机器,让它在特定的位置上画圆圈,让那个位置改变。
- Also you will need to give it a way to recognize if its circle has been clicked by giving it a contains(Point p) method. One way to do this is to use a Shape object, or you can roll your own method.
- 您还需要通过给它一个contains(Point p)方法来识别它的圆是否被单击。一种方法是使用一个Shape对象,或者您可以使用自己的方法。
- Give FiveEyes a
List<Pupil>
that in reality is anArrayList<Pupil>
and fill it with Pupil objects. - 给五个眼睛一个列表 <学生> ,实际上是一个数组列表 <学生> ,然后用学生对象填充它。
- In FiveEyes
paintComponent(...)
method, iterate through this List telling each Pupil to draw itself. - 在FiveEyes paintComponent(…)方法中,遍历这个列表,告诉每个小学生画自己。
- In your FiveEyes MouseAdapter's
mousePressed(...)
method, iterate through your Pupil List to see if a Pupil has been clicked on. If so, move it. - 在您的FiveEyes MouseAdapter的mousePressed(…)方法中,遍历您的瞳孔列表,看看是否单击了一个瞳孔。如果是这样,移动它。
- Alternatively, you could create a Pupil BufferedImage, put it into an ImageIcon, and put that into a JLabel, and then allow your FiveEyes class's MouseAdapter to drag the labels around.
- 或者,您可以创建一个小学生BufferedImage,并将其放入ImageIcon,并将其放入JLabel,然后允许FiveEyes类的MouseAdapter拖动标签。
#2
3
First of all, this code
首先,这段代码
mh = new MouseHandler();
this.addMouseListener(mh);
this.addMouseMotionListener(mh);
must only be called once. You're adding millions of mouse handlers to the component!
只能叫一次。您正在向组件添加数百万鼠标处理程序!
And you need five instances of Pupil
, one for each eye. Right now, you have only one, so of course the rendering will only yield one result.
你需要五个瞳孔,每只眼睛一个。现在,您只有一个结果,因此渲染当然只会产生一个结果。
Lastly, you must make sure that only one eye is "active" at a time (i.e. not all of them should receive mouse events or not all of them should process them).
最后,您必须确保每次只有一只眼睛是“活动的”(即不是所有的眼睛都应该接收鼠标事件,也不是所有的眼睛都应该处理它们)。
#1
3
You have Pupil extend JPanel, but really shouldn't be doing that. Instead, use the concepts that you've learned in your current Pupil class -- how to draw a movable circle, and extend it in the larger FiveEyes class, only this time create a List<Pupil>
and draw them. My suggestions:
你有瞳孔扩展JPanel,但真的不应该这么做。相反,使用你在当前的学生课程中学到的概念——如何绘制一个可移动的圆圈,并在较大的五眼课程中扩展它,只是这一次创建一个列表 <瞳孔> 并绘制它们。我的建议:
- Make Pupil not extend JPanel. Instead give it the machinery to draw circles in certain locations and to have that location changed.
- 使瞳孔不延伸JPanel。相反,给它一些机器,让它在特定的位置上画圆圈,让那个位置改变。
- Also you will need to give it a way to recognize if its circle has been clicked by giving it a contains(Point p) method. One way to do this is to use a Shape object, or you can roll your own method.
- 您还需要通过给它一个contains(Point p)方法来识别它的圆是否被单击。一种方法是使用一个Shape对象,或者您可以使用自己的方法。
- Give FiveEyes a
List<Pupil>
that in reality is anArrayList<Pupil>
and fill it with Pupil objects. - 给五个眼睛一个列表 <学生> ,实际上是一个数组列表 <学生> ,然后用学生对象填充它。
- In FiveEyes
paintComponent(...)
method, iterate through this List telling each Pupil to draw itself. - 在FiveEyes paintComponent(…)方法中,遍历这个列表,告诉每个小学生画自己。
- In your FiveEyes MouseAdapter's
mousePressed(...)
method, iterate through your Pupil List to see if a Pupil has been clicked on. If so, move it. - 在您的FiveEyes MouseAdapter的mousePressed(…)方法中,遍历您的瞳孔列表,看看是否单击了一个瞳孔。如果是这样,移动它。
- Alternatively, you could create a Pupil BufferedImage, put it into an ImageIcon, and put that into a JLabel, and then allow your FiveEyes class's MouseAdapter to drag the labels around.
- 或者,您可以创建一个小学生BufferedImage,并将其放入ImageIcon,并将其放入JLabel,然后允许FiveEyes类的MouseAdapter拖动标签。
#2
3
First of all, this code
首先,这段代码
mh = new MouseHandler();
this.addMouseListener(mh);
this.addMouseMotionListener(mh);
must only be called once. You're adding millions of mouse handlers to the component!
只能叫一次。您正在向组件添加数百万鼠标处理程序!
And you need five instances of Pupil
, one for each eye. Right now, you have only one, so of course the rendering will only yield one result.
你需要五个瞳孔,每只眼睛一个。现在,您只有一个结果,因此渲染当然只会产生一个结果。
Lastly, you must make sure that only one eye is "active" at a time (i.e. not all of them should receive mouse events or not all of them should process them).
最后,您必须确保每次只有一只眼睛是“活动的”(即不是所有的眼睛都应该接收鼠标事件,也不是所有的眼睛都应该处理它们)。