Java程序用于检测形状内的鼠标点击 – 程序不起作用

huangapple 未分类评论48阅读模式
英文:

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 &gt;= 0) {

            surf.repaint();
            alpha_ellipse += -0.01f;

            if (alpha_ellipse &lt; 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 &gt;= 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 &lt; 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(()-&gt;surf.setAlphaEllipse(alpha_ellipse));

		try {
			Thread.sleep(50);
		} catch (InterruptedException ex) {
			ex.printStackTrace();
		}
	}
}

Side note: consider using Swing Timer instead of a thread.

huangapple
  • 本文由 发表于 2020年7月23日 22:21:13
  • 转载请务必保留本文链接:https://java.coder-hub.com/63056490.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定