2013-05-19 5 views
0

멀티 스레딩을 사용하여 JFrame 내부에서 튀는 공을 그려 봅니다. 업데이트하고 인쇄 할 각 공의 좌표를 가져올 수 있지만 볼을 표시 할 수 없습니다. 나는 그래픽이 그다지 강하지 못해 내가 무엇을 놓치고 있는지 잘 모르겠습니다. Ball의 각 인스턴스를 내 프레임 안에있는 패널에 추가해야한다고 생각하지만, 시도했을 때 변경되지 않았습니다. 또한 생략 한 JFrame을 보는 데 사용되는 클래스가 있습니다. 내가 여기서 무엇을 놓치고 있니?멀티 스레드 튀어 오르는 공, 표시 공 문제

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.util.Random; 
import javax.swing.JPanel; 

public class Ball extends JPanel implements Runnable { 
JPanel pan; 
private static int radius = 10; 
private Color color; 
private int xPos; 
private int yPos; 
private int dx; 
private int dy; 
Dimension d; 

public Ball(JPanel p) { 
    Random r = new Random(); 
    this.pan = p; 
    this.d = pan.getSize(); 
    xPos = r.nextInt(d.width-50)+25; 
    yPos = r.nextInt(d.height-50)+25; 
    dx = r.nextInt(3)+1; 
    dy = r.nextInt(3)+1; 
    color = new Color(r.nextInt(255*255*255)); 
    paintComponent(pan.getGraphics()); 
} 

public void move() { 
    xPos += dx; 
    yPos += dy; 
    if (xPos+radius <= 0 || xPos+radius >= d.width) 
     dx = -dx; 
    if (yPos+radius <= 0 || yPos+radius >= d.height) 
     dy = -dy; 
} 

public void paintComponent(Graphics g) { 
    super.paintComponent(g); 
    g.setColor(color); 
    g.fillOval(xPos-radius, yPos-radius, 2*radius, 2*radius); 
    g.dispose(); 
} 

public void animate() { 
    paintComponent(pan.getGraphics()); 
    move(); 
    //pan.validate();//this didn't 
    //pan.repaint();// work 
    try { 
     Thread.sleep(40); 
    } catch (InterruptedException e) {} 
} 

public void run() { 
    while(true) 
     animate(); 
} 
} 

BallTracker

import java.util.ArrayList; 

public class BallTracker { 
private ArrayList<Ball> balls; 

public BallTracker() { 
    balls = new ArrayList<Ball>(); 
} 

public void addBall(Ball b) { 
    balls.add(b); 
    Thread t = new Thread(b); 
    t.start(); 
} 
} 

BallFrame는

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class BallFrame extends JFrame { 
public static final int WIDTH = 500; 
public static final int HEIGHT = 550; 
private BallTracker tracker; 
private JPanel ballPanel; 
private JPanel buttonPanel; 

public BallFrame() { 
    super("BallFrame"); 
    tracker = new BallTracker(); 

    // set up ball panel 
    ballPanel = new JPanel(); 
    ballPanel.setSize(WIDTH, 500); 

    // listener to add a new ball to tracker 
    class bListener implements ActionListener { 
     public void actionPerformed(ActionEvent event) { 
      Ball b = new Ball(ballPanel); 
      tracker.addBall(b); 

     } 
    } 

    // set up button panel 
    buttonPanel = new JPanel(); 
    buttonPanel.setSize(WIDTH, 50); 
    JButton addBallButton = new JButton(); 
    addBallButton.setText("Add ball"); 
    addBallButton.addActionListener(new bListener()); 
    buttonPanel.add(addBallButton); 

    // add panels to frame 
    add(buttonPanel, BorderLayout.SOUTH); 
    add(ballPanel, BorderLayout.CENTER); 
    setSize(WIDTH, HEIGHT); 
} 
} 
+3

애니메이션 엔진으로 단일 스레드를 사용해야하며 컬렉션 볼을 반복하고 단일 스레드 내에서 업데이트해야합니다. 재 페인트가 컨트롤의 바깥 쪽에서 발생할 수 있으므로 모델 값이 업데이트되거나 페인팅 된 동안 모델 값을 보호해야합니다. – MadProgrammer

+0

예제 (http://stackoverflow.com/questions/14593678/multiple-bouncing-balls-thread -issue/14593761 # 14593761) 및 [여기] (http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) – MadProgrammer

+0

대체 [여기] (http://stackoverflow.com/questions/) 15078835/i-am-make-ball-make-ball-slowly-move/15079240 # 15079240) 및 [여기] (http://stackoverflow.com/questions/15352969/drawing-2-balls-to-move-in -different-direction-on-java-but-one-disappeared/15353052 # 15353052) 스레드 대신 javax.swing.Timer를 사용합니다. – MadProgrammer

답변

1

그것은 당신의 볼이 인 JPanel을 확장하고 페인트 방법이 있지만, 당신의 ballPanel이 그림을 할 필요 것 같다 당신의 공은 실제로 패널 일 필요는없는 것 같습니다.

set up ball panel 
ballPanel = new JPanel(); 
ballPanel.setSize(WIDTH, 500); 
1

나는 주로 내가 여기에 그릴하려고하는 방식에 문제를 찾고 있었다, 그리고 왜 볼이 어떤 추가되지 않습니다

  1. 공을 볼 수 없습니다 패널.
  2. 볼을 패널에 추가하더라도 공에는 크기가 없으므로 페인트 할 것이 없습니다.
  3. 패널에 크기를 지정해도 볼 패널이 불투명하기 때문에 볼 하나만 나타납니다.
  4. 코드가 볼 패널 내의 위치에 볼을 페인트하려고합니다. 대신 볼 패널 내의 위치 (0, 0)에 볼을 페인팅 한 다음 부모 컨테이너를 기준으로 볼 패널의 위치를 ​​설정해야합니다.
  5. 부모 컨테이너는 null 레이아웃을 사용해야하므로 무작위로 볼 패널의 위치를 ​​설정할 수 있습니다. 나는 다른 문제도있다 확신

...

나는 당신이 멀티 스레딩에 대해 잊지 및 사용자 정의 그림과 타이머를 사용하는 기초에서 시작하는 것이 좋습니다.

+0

나는 당신의 생각을 고려했다. ballPanel을 내 Ball 생성자에 전달하고 패널을 사용하여 그래픽 컨텍스트/치수를 가져와야했다. 그것은 지금 작동, 유일한 문제는 줄무늬입니다, 기본적으로 공의 이전 위치는 여전히 존재합니다. 흰색 타원을 그려 dx/dy를 늘리고 색칠 된 타원을 그려서 지우려고했지만 공이 번쩍 들립니다. 모든 공을 지우지 않고 패널을 지울 수있는 방법이 있습니까? – user2313498

+0

다른 문제가 있음을 알았습니다. 커스텀 페인팅은 paint() 메쏘드가 아니라'paintComponent()'메쏘드에서 끝난 것이므로 super.paintComponent()를 호출 할 필요가 있습니다. – camickr

+0

예, 실제로 그걸 고쳤습니다.하지만 여전히 볼이 줄무늬를 만듭니다. 내 코드를 업데이트했습니다. – user2313498