2015-12-29 53 views
4

我想實現一個繪製兩隻眼睛的面板,它根據鼠標光標是否在上面而向上看,向中心或向下看,內部或眼睛下方。我第一次使用這個代碼,以使眼睛:一個Swing初學者,想做一個小動眼睛的Java GUI練習但是卡住了

public class EyesPanel extends JPanel implements ActionListener { 
    // images 
    public void paintComponent(Graphics g) { 
     super.paintComponents(g); 
     g.drawOval(130, 100, 120, 120); 
     g.drawOval(250, 100, 120, 120); 
     g.fillOval(175, y, 30, 30); // x: 175 y: 145 
     g.fillOval(295, y, 30, 30); // x: 295 y: 145 
    } 

Eyes

,然後及時添加事件偵聽器,使這個類的作品,但這裏是我堅持的部分。我知道如何使圖形移動(ActionListener),我知道如何實現MouseInputListener(擴展MouseInputListener)。但是,將這兩者結合起來讓我感到沮喪。任何人都可以告訴我怎麼做,給我一個示例代碼可以非常有幫助。

下面是我的代碼,到目前爲止,沒有一個運作和完整代碼:

public class EyesPanel extends JPanel implements ActionListener { 
    private JPanel panel; 
    private int y; 
    private int dy; 
    private Timer t; 
    private Mouse move; 

    public EyesPanel() { 
     dy = 5; 
     y = 145; 

     // mouse detector 
     this.addMouseListener(new Mouse()); 
     this.addMouseMotionListener(new Mouse()); 

     // Timer 
     t = new Timer(100, this); 
    } 

    // images 
    public void paintComponent(Graphics g) { 
     super.paintComponents(g); 
     g.drawOval(130, 100, 120, 120); 
     g.drawOval(250, 100, 120, 120); 
     g.fillOval(175, y, 30, 30); // x: 175 y: 145 
     g.fillOval(295, y, 30, 30); // x: 295 y: 145 
    } 

    public void actionPerformed(ActionEvent event) { 
     moveDown();  //➜ not complete, don't know how to implement 
    } 

    // move up 
    private void moveUp() { 
     if (move.move() == 1) { 
      t.start(); 
      y = y + dy; 
      repaint(); 
     } else { 
      t.stop(); 
     } 
    } 

    // move down 
    private void moveDown() { 
     if (move.move() == -1) { 
      t.start(); 
      y = y - dy; 
      repaint(); 
     } else { 
      t.stop(); 
     } 
    } 
    // ➜ not complete, trying, but no clue 
} 

我的鼠標事件類:

public class Mouse extends MouseInputAdapter { 
    private int y; 

    public void mouseEntered(MouseEvent event) { 
     JPanel pane = (JPanel) event.getSource(); 
     y = pane.getHeight();  // ➜ not complete 
    } 
} 
+0

看看這裏:https://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html – slambeth

+1

你不需要任何的ActionListener或定時器。你需要的是一個MouseMotionListener。在其mouseMoved()方法中,存儲鼠標的新座標,然後調用repaint()。在paintComponent()中,使用鼠標的座標來計算眼睛應該看的位置。 –

回答

3

讓你的班級變得像這樣,並且你的班級取消了super.paintComponents(g);

import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseEvent; 

import java.awt.event.MouseMotionListener; 
import java.util.Timer; 

import javax.swing.JPanel; 


public class EyesPanel extends JPanel implements ActionListener,MouseMotionListener{ 
    private JPanel panel; 
    private int y; 
    private int dy; 
    private Timer t; 


    public EyesPanel() { 
     dy = 5; 
     y = 145; 

     // mouse detector 
     this.addMouseMotionListener(this); 


     // Timer 

    } 

    // images 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     g.drawOval(130, 100, 120, 120); 
     g.drawOval(250, 100, 120, 120); 
     g.fillOval(175, y, 30, 30); // x: 175 y: 145 
     g.fillOval(295, y, 30, 30); // x: 295 y: 145 
    } 



    // move up 

    // ➜ not complete, trying, but no clue 




@Override 
public void actionPerformed(ActionEvent arg0) { 
    // TODO Auto-generated method stub 

} 

    @Override 
    public void mouseDragged(MouseEvent arg0) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void mouseMoved(MouseEvent arg0) { 
     // TODO Auto-generated method stub 
     System.out.println(arg0.getY()); 
     if(arg0.getY() > 101 && arg0.getY() < 187) 
     y = arg0.getY(); 
     repaint(); 

    } 


} 
0

您正在尋找的方法mouseMoved而不是mouseEntered

2

讓眼睛跟隨光標的數學並不那麼複雜。

這是我的GUI看起來像。

Moving Eyes

  1. 我創建了一個眼類來保存外眼窩的中心和內眼球的中心。

  2. 我創建了一個MovingEyes類來創建JFrame和一個DrawingPanel類,以在DrawingPanel上繪製眼睛。我創建了Eye數組來在MovingEyes類的構造函數中保存2個眼睛。

  3. DrawingPanel類的paintComponent方法只會吸引眼球。黑眼球中心的計算髮生在另一班。我創建了一些便利方法,以便我可以繪製一個圓,並使用中心點和半徑填充一個圓。

  4. EyeballListener類執行兩個黑色眼球的計算。我們計算從眼窩中心延伸到鼠標指針的線的θ角(弧度)。然後,我們使用theta角度和眼球距離來計算黑色眼球的x和y位置。

這是代碼。

package com.ggl.testing; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Point; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class MovingEyes implements Runnable { 

    private static final int drawingWidth = 400; 
    private static final int drawingHeight = 400; 
    private static final int eyeballHeight = 150; 
    private static final int eyeballWidthMargin = 125; 
    private static final int eyeballOuterRadius = 50; 
    private static final int eyeballInnerRadius = 20; 

    private DrawingPanel drawingPanel; 

    private Eye[] eyes; 

    private JFrame frame; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new MovingEyes()); 
    } 

    public MovingEyes() { 
     this.eyes = new Eye[2]; 
     this.eyes[0] = new Eye(new Point(eyeballWidthMargin, eyeballHeight)); 
     this.eyes[1] = new Eye(new Point(drawingWidth - eyeballWidthMargin, 
       eyeballHeight)); 
    } 

    @Override 
    public void run() { 
     frame = new JFrame("Moving Eyes"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     drawingPanel = new DrawingPanel(); 
     frame.add(drawingPanel); 

     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public class DrawingPanel extends JPanel { 

     private static final long serialVersionUID = -2977860217912678180L; 

     public DrawingPanel() { 
      this.addMouseMotionListener(new EyeballListener()); 
      this.setBackground(Color.WHITE); 
      this.setPreferredSize(new Dimension(drawingWidth, drawingHeight)); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      g.setColor(Color.BLACK); 

      for (Eye eye : eyes) { 
       drawCircle(g, eye.getOrigin(), eyeballOuterRadius); 
       fillCircle(g, eye.getEyeballOrigin(), eyeballInnerRadius); 
      } 
     } 

     private void drawCircle(Graphics g, Point origin, int radius) { 
      g.drawOval(origin.x - radius, origin.y - radius, radius + radius, 
        radius + radius); 
     } 

     private void fillCircle(Graphics g, Point origin, int radius) { 
      g.fillOval(origin.x - radius, origin.y - radius, radius + radius, 
        radius + radius); 
     } 

    } 

    public class Eye { 
     private final Point origin; 
     private Point eyeballOrigin; 

     public Eye(Point origin) { 
      this.origin = origin; 
      this.eyeballOrigin = origin; 
     } 

     public Point getEyeballOrigin() { 
      return eyeballOrigin; 
     } 

     public void setEyeballOrigin(Point eyeballOrigin) { 
      this.eyeballOrigin = eyeballOrigin; 
     } 

     public Point getOrigin() { 
      return origin; 
     } 

    } 

    public class EyeballListener extends MouseMotionAdapter { 

     private final double eyeballDistance = eyeballOuterRadius 
       - eyeballInnerRadius - 5; 

     @Override 
     public void mouseMoved(MouseEvent event) { 
      Point p = event.getPoint(); 
      for (Eye eye : eyes) { 
       Point origin = eye.getOrigin(); 
       double theta = Math.atan2((double) (p.y - origin.y), 
         (double) (p.x - origin.x)); 
       int x = (int) Math.round(Math.cos(theta) * eyeballDistance) 
         + origin.x; 
       int y = (int) Math.round(Math.sin(theta) * eyeballDistance) 
         + origin.y; 
       eye.setEyeballOrigin(new Point(x, y)); 
      } 

      drawingPanel.repaint(); 
     } 

    } 

}