在一个JFrame中同时处理两个JPanel

时间:2014-03-09 14:32:30

标签: java multithreading swing animation graphics

我是java swing的新手。在尝试使用图形时,我会遇到这种情况。 我无法在网络上找到合适的解决方案。所以我想在这里发帖。

所以现在让我们来解决我的问题。首先,我将解释我想做什么。然后我将解释我的问题。

我试图让两个球在JFrame中同时向不同方向移动。 (基本上我想做类似连锁反应的游戏,当你点击一个装满的盒子时,球会同时向不同的方向移动)。

这里我创建两个(截至目前)两个球的JPanels,我试图同时在JFrame上移动。

这是我试过的代码,

public class chainGraphics扩展了JPanel实现的Runnable {

int oldX,oldY,newX,newY;
int changeX,changeY;
Container myPane;
public chainGraphics(int oldX,int oldY,int newX,int newY,Container myPane) {
    // TODO Auto-generated constructor stub
    this.myPane=myPane;
    this.oldX=oldX;
    this.oldY=oldY;
    this.newX=newX;
    this.newY=newY;
    myPane.add(this);

}

public void paintComponent(Graphics g) {

    //super.paintComponent(g);
    System.out.println("hj");
    g.drawOval(changeX,changeY, 40, 40);

}


@Override
public void run()   {


    System.out.println("hii");
    changeX =oldX;
    changeY = oldY;

    if((newY-oldY)==0){
        if(oldX<newX){
            for(int i=oldX;i<newX;i++){
                System.out.println("hii123");
                changeX = i;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }

                repaint();
            }
        }
        else    {
            for(int i=oldX;i>newX;i--){
                changeX=i;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                repaint();
            }
        }

    }
    if((newX-oldX)==0){
        if(oldY<newY){
            for(int i=oldY;i<newY;i++){
                changeY=i;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                repaint();
            }
        }
        else    {
            for(int i=oldY;i>newY;i--){
                changeY=i;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                repaint();
            }
        }       
    }
}

public static void main(String[] args)  {

    JFrame gui = new JFrame();
    gui.setTitle("Chain Reaction ;-) ");
    gui.setSize(650,650);
    gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    gui.setLocationRelativeTo(null);
    gui.setVisible(true);
    Container Pane = gui.getContentPane();
    chainGraphics g = new chainGraphics(100,200,300,200,Pane);  
            chainGraphics g1 = new chainGraphics(200,100,200,300,Pane); 
    Thread t1 = new Thread(g);
    t1.start();     
    Thread t2 = new Thread(g1);
    t2.start();


    try {
        t1.join();
                    t2.join();      
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

}

}

在这里我看不到两个球同时移动。我猜有一个问题。 我能够看到球只沿y方向移动。 (但我希望两个球同时移动,因为我创造了两个线程)

我还注意到我先创建g1对象然后再创建g对象, 然后球只沿x方向移动。

我认为Jframe一次只能处理1个JPanel。 (我将JPanel添加到Frame彻底的构造函数中)。因此,最后将JPanel添加到框架中,它允许对其进行处理。是这样吗 ? 如果我现在该怎么办。我的要求是我想在不同方向同时移动球。 感谢。

1 个答案:

答案 0 :(得分:3)

  

“不,我试图用两个线程画两个球”

  1. 不要尝试将面板的两个实例添加到容器中。只需使用Ball个对象的数据结构(我更喜欢List),然后在paintComponent方法中循环它们。每个球都可以使用drawBall(Graphics g)方法,您可以使用paintComponent方法调用该方法,并将Graphics上下文

  2. 传递给它
  3. 使用Swing Timer并忘记线程。 Thread.sleep不是你在Swing的朋友。请参阅How to use Swing Timers

  4. 在计时器中,只需更改每个Ball对象的位置/轨迹,然后调用repaint()。您可以在Ball课程中使用可改变方向的方法。

  5. 在Event Dispatch Thread上运行Swing应用程序。您可以将main方法代码包装在SwingUtilities.invokeLater..中。请参阅Initial Threads


  6. 这是一个例子

    enter image description here

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class MoveBalls extends JPanel {
    
        private static final int D_W = 500;
        private static final int D_H = 300;
    
        private List<Ball> balls;
    
        public MoveBalls() {
            Random rand = new Random();
            balls = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                int randX = rand.nextInt(D_W);
                int randY = rand.nextInt(D_H);
                balls.add(new Ball(randX, randY));
            }
    
            Timer timer = new Timer(15, new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    for (Ball ball : balls) {
                        ball.animate();
                    }
                    repaint();
                }
            });
            timer.start();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (Ball ball : balls) {
                ball.drawBall(g);
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            return new Dimension(D_W, D_H);
        }
    
        public class Ball {
    
            int x = 0;
            int y = 0; // Current ball position
            int dx = 4; // Increment on ball's x-coordinate
            int dy = 4; // Increment on ball's y-coordinate
            int radius = 15; // Ball radius
    
            public Ball(int x, int y) {
                this.x = x;
                this.y = y;
            }
            Color color = new Color((int) (Math.random() * 256),
                    (int) (Math.random() * 256), (int) (Math.random() * 256));
    
            public void drawBall(Graphics g) {
                g.setColor(color);
                g.fillOval(x - radius, y - radius,
                        radius * 2, radius * 2);
            }
    
            public void animate() {
                if (x < 0 || x > getWidth()) {
                    dx = -dx;
                }
                if (y < 0 || y > getHeight()) {
                    dy = -dy;
                }
                // Adjust ball position
                x += dx;
                y += dy;
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame();
                    frame.add(new MoveBalls());
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    }