2015-04-05 18 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

相關問題