英文:
Java program to detect a mouse click within a shape - program not working
问题
以下是翻译好的部分:
public class Surface extends JPanel {
private Ellipse2D ellipse;
private float alpha_ellipse; // 这个变量将用于控制椭圆的透明度
public Surface() {
initSurface();
}
private void initSurface() {
addMouseListener(new HitTestAdapter(this)); // 将Surface实例传递给鼠标适配器类
ellipse = new Ellipse2D.Float(120f, 30f, 60f, 60f);
alpha_ellipse = 1f;
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(new Color(50, 50, 50));
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(rh);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
alpha_ellipse));
g2d.fill(ellipse);
g2d.dispose();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
public Ellipse2D getEllipse() {
return ellipse;
}
public float getAlphaEllipse() {
return alpha_ellipse;
}
}
public class HitTestAdapter extends MouseAdapter implements Runnable {
private Thread ellipseAnimator;
private Surface surf;
float alpha_ellipse;
public HitTestAdapter(Surface surface) {
surf = surface;
}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (surf.getEllipse().contains(x, y)) {
ellipseAnimator = new Thread(this);
ellipseAnimator.start();
}
}
@Override
public void run() {
alpha_ellipse = surf.getAlphaEllipse();
while (alpha_ellipse >= 0) {
surf.repaint();
alpha_ellipse += -0.01f;
if (alpha_ellipse < 0) {
alpha_ellipse = 0;
}
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(Surface.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
英文:
I'm following a Java 2D tutorial and have got stuck on a program written to display a rectangle and ellipse which should fade in colour when clicked ...only nothing happens and I cannot work out why. I modified the original code slightly by passing the Jpanel instance to the HitTest class constructor. By tracing through with the debugger I've established that the program does detect a mouse click in the displayed shape and creates a thread to adjust the colour - but for some reason the colour does not adjust and stays the same. I thought the problem might be to do with where the repaint method is being called but not sure? Thanks in advance for any help received.
Here's some of the code:
public class Surface extends JPanel {
private Ellipse2D ellipse;
private float alpha_ellipse; //This variable will be used to control the transparency of the ellipse
public Surface() {
initSurface();
}
private void initSurface() {
addMouseListener(new HitTestAdapter(this)); //pass instance of surface to mouse adapter class
ellipse = new Ellipse2D.Float(120f, 30f, 60f, 60f);
alpha_ellipse = 1f;
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.setPaint(new Color(50, 50, 50));
RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(rh);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, // set the transparency using
alpha_ellipse)); //alpha_ellipse value calculated in a thread
g2d.fill(ellipse);
g2d.dispose();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
public Ellipse2D getEllipse() {
return ellipse;
}
public float getAlphaEllipse() {
return alpha_ellipse;
}
}
public class HitTestAdapter extends MouseAdapter
implements Runnable{
private RectRunnable rectAnimator;
private Thread ellipseAnimator;
private Surface surf;
float alpha_ellipse;
public HitTestAdapter(Surface surface) { // I passed surface as a parameter to get to Surface class methods from this class
surf = surface;
}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
if (surf.getEllipse().contains(x, y)) { //if we press inside the ellipse
ellipseAnimator = new Thread(this); // a new thread is created
ellipseAnimator.start();
}
}
@Override
public void run() {
alpha_ellipse= surf.getAlphaEllipse();
while (alpha_ellipse >= 0) {
surf.repaint();
alpha_ellipse += -0.01f;
if (alpha_ellipse < 0) {
alpha_ellipse = 0;
}
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
Logger.getLogger(Surface.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
答案1
得分: 0
看一下在run
方法中需要的注释更改:
@Override
public void run() {
alpha_ellipse = surf.getAlphaEllipse();
while (alpha_ellipse >= 0) {
surf.repaint();
// 如果 alpha_ellipse 变为负数,它将永远不会再变为正数
// 所以你可以简单地停止循环
alpha_ellipse += -0.01f;
if (alpha_ellipse < 0) {
alpha_ellipse = 0;
}
// 需要在 Surface 中设置新的 alpha 值。在 Surface 中添加一个 setter 方法
// 对 Swing GUI 的更改必须在 EDT 上执行,因此使用了 invokeLater
SwingUtilities.invokeLater(() -> surf.setAlphaEllipse(alpha_ellipse));
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
附注:考虑使用 Swing Timer 替代线程。
英文:
See the commented changes needed in run
:
@Override
public void run() {
alpha_ellipse= surf.getAlphaEllipse();
while (alpha_ellipse >= 0) {
surf.repaint();
//if alpha_ellipse becomes negative it will never become positive again
//so you can simply stop
alpha_ellipse += -0.01f;
if (alpha_ellipse < 0) {
alpha_ellipse = 0;
}
//need to set the new alpha in Surface. Add a setter to Surface
//a change to swing gui must be done on the EDT hence the use of invokeLater
SwingUtilities.invokeLater(()->surf.setAlphaEllipse(alpha_ellipse));
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
Side note: consider using Swing Timer instead of a thread.
专注分享java语言的经验与见解,让所有开发者获益!
评论