2015-04-05 60 views
1

我在做一个禁止使用JButton的程序。我被要求在awt矩形上使用鼠标事件监听器。点击按钮的结果应该是:repaint导致mouseListener注册没有发生的点击

  • 增加10到一个变量在另一个类中
  • 重绘表示燃料米的矩形

的问题是,当我把在重绘方法mouseClicked侦听器的结尾,在第一次单击之后,侦听器将注册多次点击而不是一次。下面是实现相同类型的按钮替换I使用的一个程序(在此发现StackExchange):

import java.awt.*; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseListener; 

import javax.swing.*; 

public class Gui2 extends JFrame { 
    JFrame frame = new JFrame(); 
    MyDrawPanel drawpanel = new MyDrawPanel(); 

    public static void main(String[] args) { 
     Gui2 gui = new Gui2(); 
     gui.go(); 
    } 

    public void go() { 

     frame.getContentPane().add(drawpanel); 
     // frame.addMouseListener(this); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(300, 300); 
     frame.setVisible(true); 

    } 

} 

class MyDrawPanel extends JComponent implements MouseListener { 
    private boolean mouseClicked = false; 

    public void paintComponent(Graphics g) { 

     int red = (int) (Math.random() * 255); 
     int green = (int) (Math.random() * 255); 
     int blue = (int) (Math.random() * 255); 
     Color startrandomColor = new Color(red, green, blue); 

     red = (int) (Math.random() * 255); 
     green = (int) (Math.random() * 255); 
     blue = (int) (Math.random() * 255); 
     Color endrandomColor = new Color(red, green, blue); 

     Graphics2D g2d = (Graphics2D) g; 
     this.addMouseListener(this); 
     GradientPaint gradient = new GradientPaint(70, 70, startrandomColor, 
       150, 150, endrandomColor); 

     g2d.setPaint(gradient); 
     g2d.fillOval(70, 70, 100, 100); 

    } 

    @Override 
    public void mouseClicked(MouseEvent e) { 
     if ((e.getButton() == 1) 
       && (e.getX() >= 70 && e.getX() <= 170 && e.getY() >= 70 && e 
       .getY() <= 170)) { 
      mouseClicked = true; 
      this.repaint(); 
      if(mouseClicked == true){ 
       System.out.println("click"); 
      } 
      // JOptionPane.showMessageDialog(null,e.getX()+ "\n" + e.getY()); 
     } 

    } 

    @Override 
    public void mouseEntered(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseExited(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mousePressed(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     // TODO Auto-generated method stub 

    } 

} 

当在帧中的椭圆被点击一次时,一个“点击”被打印在控制台上。当它由于某种原因第二次点击时,它会打印2“点击”。对于第三次点击,它打印3等等。为什么repaint方法会这样做,以及如何在awt椭圆上使用它,而无需注册多个点击?

+0

请参阅编辑回答。 – 2015-04-05 04:00:59

+0

@AndrewThompson:因为它在项目规范中。 – grumpbot 2015-04-06 00:27:38

回答

2

不要添加的MouseListener中的paintComponent方法里面的,将继续 MouseListeners添加多到您的组件,所以以后每次鼠标点击,随机化和重新油漆会被多次调用,而不是你想要什么。在类的构造函数中添加一次,解决问题。请记住,paintComponent方法应该仅用于绘画和绘画,而不适用于更改组件,添加侦听器,读取图像或其他任何内容。事实上,我会在MouseListener中设置随机颜色,而不是在paintComponent中,否则当您调整GUI大小时颜色会发生变化。为什么布尔变量的方式?另外,不要忘记将super.paintComponent调用添加到paintComponent重写中。我也使用mousePressed,而不是mouseClicked,因为mouseClicked可能不可靠。例如:

import java.awt.*; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import javax.swing.*; 

public class Gui2 { 
    JFrame frame = new JFrame(); 
    MyDrawPanel drawpanel = new MyDrawPanel(); 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      Gui2 gui = new Gui2(); 
      gui.go(); 
     } 
     }); 
    } 

    public void go() { 
     frame.getContentPane().add(drawpanel); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 
} 

class MyDrawPanel extends JComponent { 
    private static final int PREF_W = 240; 
    private static final int PREF_H = PREF_W; 
    private static final double RGB_MAX = 255; 
    private static final double ELLIPSE_X = 70; 
    private static final double ELLIPSE_WIDTH = PREF_W - 2 * ELLIPSE_X; 
    private int red; 
    private int green; 
    private int blue; 
    private Color startrandomColor; 
    private Color endrandomColor; 
    private Ellipse2D ellipse = new Ellipse2D.Double(ELLIPSE_X, ELLIPSE_X, 
     ELLIPSE_WIDTH, ELLIPSE_WIDTH); 

    public MyDrawPanel() { 
     addMouseListener(new MyMouseAdapter()); 
     setRandomGradient(); 
    } 

    private void setRandomGradient() { 
     red = (int) (Math.random() * RGB_MAX); 
     green = (int) (Math.random() * RGB_MAX); 
     blue = (int) (Math.random() * RGB_MAX); 
     startrandomColor = new Color(red, green, blue); 
     red = (int) (Math.random() * RGB_MAX); 
     green = (int) (Math.random() * RGB_MAX); 
     blue = (int) (Math.random() * RGB_MAX); 
     endrandomColor = new Color(red, green, blue); 
    } 

    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     GradientPaint gradient = new GradientPaint(70, 70, startrandomColor, 150, 
      150, endrandomColor); 

     g2d.setPaint(gradient); 
     g2d.fill(ellipse); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
     return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    private class MyMouseAdapter extends MouseAdapter { 
     @Override 
     public void mousePressed(MouseEvent e) { 
     if (ellipse.contains(e.getPoint())) { 
      setRandomGradient(); 
      repaint(); 
     } 
     } 
    } 
} 

还要注意的是,如果你使用Ellipse2D的,你如果在MouseListener的块被大大简化,这大大降低了您的恶性很难找到错误的风险:

@Override 
    public void mousePressed(MouseEvent e) { 
    if (ellipse.contains(e.getPoint())) { 
     setRandomGradient(); 
     repaint(); 
    } 
    } 
+0

非常感谢。我曾尝试将侦听器与paintComponent分开,但从未想过要使用继承MouseAdapter类的类。 – grumpbot 2015-04-06 00:26:54