2012-05-11 7 views
1

Java로 만들려고하는 게임에 문제가 있습니다. 내 캔버스에 MouseListener를 연결하려고하지만 캔버스를 클릭해도 아무 일도 일어나지 않습니다. 나는 MouseListener를 잘못된 것에 붙일 수 있다고 생각하지만, 무엇에 붙일 지 모른다. 나는 JFrame과 캔버스에 붙이는 것을 시도했다.Canvas의 MouseListener가 작동하지 않습니다.

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 

import java.io.*; 

import javax.imageio.ImageIO; 
import javax.swing.*; 
import java.util.Random; 

public class Gravity extends Canvas { 

    public static final int screenw = 1024; 
    public static final int screenh = 768; 

    public static Random gen = new Random(); 

    public static Boolean started = false; 

    public static int[] starx = new int[100]; 
    public static int[] stary = new int[100]; 
    public static Color[] starc = new Color[100]; 

    public static JFrame frame; 
    public static Gravity canvas; 
    public static Image buffer; 
    public static Graphics bg; 

    public static int[] xh = new int[1000]; 
    public static int[] yh = new int[1000]; 

    public static int i = 0; 

    public static Image title; 

    public static ArrayList<Integer> ptx = new ArrayList<Integer>(); 
    public static ArrayList<Integer> pty = new ArrayList<Integer>(); 
    double x = 100; 
    double y = 100; 

    public Gravity(){ 
    } 

    public void paint (Graphics g) { 
     frame.addMouseListener(new MouseListener(){ 
      public void mouseClicked(MouseEvent e){ 
       started = true; 
       System.out.println("Mouse was clicked"); 
      } 

      public void mouseEntered(MouseEvent arg0) {} 
      public void mouseExited(MouseEvent arg0) {} 
      public void mousePressed(MouseEvent arg0) {} 
      public void mouseReleased(MouseEvent arg0) {} 
     }); 


     buffer = createImage(screenw, screenh); 
     bg = buffer.getGraphics(); 

     int w = getWidth(); 
     int h = getHeight(); 

     double px = getWidth()/2; 
     double py = getHeight()/2; 

     bg.setColor(Color.BLACK); 
     bg.fillRect(0, 0, w, h); //black background 

     for (int j=0; j < 100; j++){ //make stars 
      starx[j] = gen.nextInt(w); 
      stary[j] = gen.nextInt(h); 
      starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156); 
      bg.setColor(starc[j]); 
      bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2); 
      bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]); 
     } 

     try { 
      title = ImageIO.read(new ByteArrayInputStream(Base64.decode(""))); //I have omitted the Base64 code for the image for my title screen 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     bg.drawImage(title, 100, 100, null); 
     g.drawImage(buffer, 0, 0, null); 

     while (!started){ 
      try { 
       Thread.sleep(50); 
      } catch (InterruptedException e1) { 
       e1.printStackTrace(); 
      } 
     } 

     double xvel = -15; 
     double yvel = 10; 

     for (int j=0; j < 100; j++){ //store stars 
      starx[j] = gen.nextInt(w); 
      stary[j] = gen.nextInt(h); 
      starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156); 
     } 

     Image test = createImage(200,200); 
     Graphics testg = test.getGraphics(); 
     testg.drawLine(50,50,150,150); 

     while(true){ 
      g.drawImage(buffer, 0,0, null); 
      try { 
       Thread.sleep(33); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      bg.setColor(Color.BLACK); 
      bg.fillRect(0, 0, w, h); //black background 


      for (int j=0; j < 100; j++){ //draw stars 
       bg.setColor(starc[j]); 
       bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2); 
       bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]); 
      } 

      bg.setColor(Color.BLUE); 

      if (i > 0){ 
       for (int z=0; z < i-1; z++){ 
        bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1)); 
       } 
      } 

      bg.setColor(Color.CYAN); 
      bg.fillOval((int)px, (int)py, 25, 25); //planet 

      bg.setColor(Color.RED); 
      bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship 

      double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2)); 

      double m = (y-py)/(x-px); 
      double ms = Math.sqrt(Math.abs(m)); 
      if (m < 0) ms = -ms; 

      double xchg = fg; 
      double ychg = fg*ms; 

      if (x > px){ 
       xchg = -xchg; 
       ychg = -ychg; 
      } 

      xvel += xchg; 
      yvel += ychg; 

      x += xvel; 
      y += yvel; 

      ptx.add((int)x); 
      pty.add((int)y); 

      i++; 
     } 
    } 

    public static void main(String[] args){ 

     canvas = new Gravity(); 
     frame = new JFrame(); 
     frame.setSize(screenw, screenh); 
     frame.setResizable(false); 
     frame.setLocationRelativeTo(null); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(canvas); 

     frame.setVisible(true); 
    } 


    public static double dist(double x1, double y1, double x2, double y2){ 
     double x = x2-x1; 
     double y = y2-y1; 
     return Math.sqrt((x*x)+(y*y)); 
    } 
} 
+0

답변 해 주신 모든 분들께 감사드립니다. 필자는'paint()'와 Canvas의 기본 개념, 즉'paint()'가 두 번 이상 다시 실행되는 방식을 이해하지 못했습니다. 캔버스가 아닌 JPanel을 사용하도록 변경하려고합니다. – bdr9

답변

3

일반 팁 :

  1. 스윙 (예를 들어, JFrame) 구성 요소 AWT를 (예를 들어, Canvas) 혼합하지 마십시오. 캔버스 대신 대신 JPanel을 사용하고 paintComponent(Graphics)을 재정의하십시오.
  2. EDT에 Thread.sleep(n)으로 전화하지 마십시오. 대신 Timer을 기반으로 한 스윙을 사용하십시오. repaint()
  3. 페인트 방법에서 장기간 작동을 수행하지 마십시오. 특히 무한 루프를 시작하는 것이 좋습니다! 버퍼 이미지의 생성조차도 화면 크기가 변경된 경우에만 수행해야합니다. 'TODO'- BNI로 남음
  4. 페인트가 호출 될 때마다 MouseListener을 생성자에 한 번 추가하거나 메서드를 추가합니다.
  5. Nate의 모든 번호 매기기 목록을 강력히 권장합니다.

이 코드를 시험해보고 변경된 사항을 원본과 신중하게 비교하십시오.

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Dimension; 
import java.awt.event.*; 
import java.util.ArrayList; 

import java.io.*; 

import javax.imageio.ImageIO; 
import javax.swing.*; 
import java.util.Random; 

public class Gravity extends JPanel { 

    public static final int screenw = 800; 
    public static final int screenh = 600; 

    public static Random gen = new Random(); 

    public static int[] starx = new int[100]; 
    public static int[] stary = new int[100]; 
    public static Color[] starc = new Color[100]; 

    public static Image buffer; 
    public static Graphics bg; 

    public static int[] xh = new int[1000]; 
    public static int[] yh = new int[1000]; 

    public static int i = 0; 

    public static ArrayList<Integer> ptx = new ArrayList<Integer>(); 
    public static ArrayList<Integer> pty = new ArrayList<Integer>(); 
    double x = 100; 
    double y = 100; 

    Timer timer; 

    public Gravity(){ 
     // set thre PREFERRED size! 
     setPreferredSize(new Dimension(screenw, screenh)); 
     addMouseListener(new MouseListener(){ 
        public void mouseClicked(MouseEvent e){ 
         System.out.println("Mouse was clicked"); 
         timer.start(); 
        } 

        public void mouseEntered(MouseEvent arg0) {} 
        public void mouseExited(MouseEvent arg0) {} 
        public void mousePressed(MouseEvent arg0) {} 
        public void mouseReleased(MouseEvent arg0) {} 
     }); 
     ActionListener animation = new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent ae) { 
       repaint(); 
      } 
     }; 
     timer = new Timer(50, animation); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     buffer = createImage(screenw, screenh); 
     bg = buffer.getGraphics(); 

     int w = getWidth(); 
     int h = getHeight(); 

     double px = getWidth()/2; 
     double py = getHeight()/2; 

     bg.setColor(Color.BLACK); 
     bg.fillRect(0, 0, w, h); //black background 

     for (int j=0; j < 100; j++){ //make stars 
      starx[j] = gen.nextInt(w); 
      stary[j] = gen.nextInt(h); 
      starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156); 
      bg.setColor(starc[j]); 
      bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2); 
      bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]); 
     } 

     g.drawImage(buffer, 0, 0, null); 

     double xvel = -15; 
     double yvel = 10; 

     for (int j=0; j < 100; j++){ //store stars 
      starx[j] = gen.nextInt(w); 
      stary[j] = gen.nextInt(h); 
      starc[j] = new Color(gen.nextInt(100)+156, gen.nextInt(100)+156, gen.nextInt(100)+156); 
     } 

     Image test = createImage(200,200); 
     Graphics testg = test.getGraphics(); 
     testg.drawLine(50,50,150,150); 

     g.drawImage(buffer, 0,0, null); 
     try { 
      Thread.sleep(33); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     bg.setColor(Color.BLACK); 
     bg.fillRect(0, 0, w, h); //black background 


     for (int j=0; j < 100; j++){ //draw stars 
      bg.setColor(starc[j]); 
      bg.drawLine(starx[j], stary[j], starx[j]+2, stary[j]+2); 
      bg.drawLine(starx[j], stary[j]+2, starx[j]+2, stary[j]); 
     } 

     bg.setColor(Color.BLUE); 

     if (i > 0){ 
      for (int z=0; z < i-1; z++){ 
       bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z+1), pty.get(z+1)); 
      } 
     } 

     bg.setColor(Color.CYAN); 
     bg.fillOval((int)px, (int)py, 25, 25); //planet 

     bg.setColor(Color.RED); 
     bg.fillRect((int)(x-5),(int)(y-5),10,10); //ship 

     double fg = (5*50000)/(Math.pow(dist(x,y,px,py),2)); 

     double m = (y-py)/(x-px); 
     double ms = Math.sqrt(Math.abs(m)); 
     if (m < 0) ms = -ms; 

     double xchg = fg; 
     double ychg = fg*ms; 

     if (x > px){ 
      xchg = -xchg; 
      ychg = -ychg; 
     } 

     xvel += xchg; 
     yvel += ychg; 

     x += xvel; 
     y += yvel; 

     ptx.add((int)x); 
     pty.add((int)y); 

     i++; 
    } 

    public static void main(String[] args){ 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame frame = new JFrame(); 

       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.getContentPane().add(new Gravity()); 
       frame.setResizable(false); 
       frame.pack(); 

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


    public static double dist(double x1, double y1, double x2, double y2){ 
     double x = x2-x1; 
     double y = y2-y1; 
     return Math.sqrt((x*x)+(y*y)); 
    } 
} 
1

귀하의 paint() 메소드 인해 반면에, 마우스 클릭 이벤트를 처리하는 스레드를 묶는있다 (! 시작) 종료 결코 루프 : 여기 내 코드입니다. paint() Methods가 true가되기를 기다리고 있기 때문에, MouseListener의 mouseClicked()가 불려 가지 않았기 때문에, true가 개시되었습니다. 해당 루프를 제거하면 while (true) 루프가 유사한 효과를 갖습니다. paint()가 실행되는 동안 발생하는 모든 마우스 이벤트는 paint()가 반환 할 때까지 대기열에 있습니다.

+0

그것보다 더 많은 것이있었습니다. 사용자가 애니메이션을 클릭 할 때까지 끝나지 않은 이전 루프에서 잡혔습니다! –

+0

너무 사실; 그에 따라 내 대답을 업데이트했습니다. –

1

Canvas 대신 JComponent를 사용하십시오. 마우스 리스너를 해당 객체에 추가하려고합니다. 또한 paint() 메소드가 아니라 생성자에서 마우스 리스너를 설정해야합니다.

편집 : @AndrewThompson이 지적한대로 paint() 메소드를 많이 사용하고 있습니다. 코드에 대한

public Gravity() { 
    addMouseListener(new MouseListener() { 

     @Override 
     public void mouseClicked(MouseEvent e) { 
      System.out.println("Mouse was clicked"); 
     } 

     @Override 
     public void mouseEntered(MouseEvent arg0) { 
     } 

     @Override 
     public void mouseExited(MouseEvent arg0) { 
     } 

     @Override 
     public void mousePressed(MouseEvent arg0) { 
     } 

     @Override 
     public void mouseReleased(MouseEvent arg0) { 
     } 
    }); 
} 

@Override 
public void paint(Graphics g) { 

    buffer = createImage(screenw, screenh); 
    bg = buffer.getGraphics(); 

    ... 

    bg.setColor(Color.BLACK); 
    bg.fillRect(0, 0, w, h); // black background 

    for (int j = 0; j < 100; j++) { // make stars 
     ... 
    } 

    bg.drawImage(title, 100, 100, null); 
    g.drawImage(buffer, 0, 0, null); 

    double xvel = -15; 
    double yvel = 10; 

    for (int j = 0; j < 100; j++) { // store stars 
     ... 
    } 

    Image test = createImage(200, 200); 
    Graphics testg = test.getGraphics(); 
    testg.drawLine(50, 50, 150, 150); 

    g.drawImage(buffer, 0, 0, null); 
    bg.setColor(Color.BLACK); 
    bg.fillRect(0, 0, w, h); // black background 

    for (int j = 0; j < 100; j++) { // draw stars 
     ... 
    } 

    bg.setColor(Color.BLUE); 

    if (i > 0) { 
     for (int z = 0; z < i - 1; z++) { 
      bg.drawLine(ptx.get(z), pty.get(z), ptx.get(z + 1), pty.get(z + 1)); 
     } 
    } 

    bg.setColor(Color.CYAN); 
    bg.fillOval((int) px, (int) py, 25, 25); // planet 

    bg.setColor(Color.RED); 
    bg.fillRect((int) (x - 5), (int) (y - 5), 10, 10); // ship 

    .... 

    ptx.add((int) x); 
    pty.add((int) y); 
} 

public static void main(String[] args) { 
    ... 

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

    ... 
} 

주 :

  1. 을 피하게 필드 public static. 99.9 %의 시간이 필요하지 않으며 보통 나중에 문제가 발생합니다.
  2. 페인팅 코드가 불필요하게 버퍼를 사용하고있는 것처럼 보입니다. test 이미지가 현재 사용되지 않습니다!
  3. 루프를 while(true) 루프에서 제거했지만 이미지를 그리는 중이고 이미지를 수정 한 다음 이미지를 다시 그립니다. 한 번에이 작업을 수행 할 수 있습니다.
  4. paint()이 호출 될 때마다 새 버퍼를 만들고 처음부터 지우는 것이므로 Image 버퍼를 사용하지 않아야합니다. 그래픽을 직접 g으로 그립니다.
  5. paint() 메서드 내에서 I/O를 수행하지 마십시오. 구성 중 또는 백그라운드 스레드에서 이미지를로드하십시오. 포인트 형태로
관련 문제