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

我是新手到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;inewX;i--){ changeX=i; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } repaint(); } } } if((newX-oldX)==0){ if(oldY<newY){ for(int i=oldY;inewY;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. 不要尝试将面板的两个实例添加到容器中。 只需使用Ball对象的数据结构(我更喜欢List)并在paintComponent方法中循环它们。 每个球都可以有一个drawBall(Graphics g)方法,你可以在paintComponent方法中调用它,并向它传递Graphics上下文

  2. 使用Swing Timer并忘记线程。 Thread.sleep不是你在Swing中的朋友。 请参见如何使用Swing Timers

  3. 在Timer中,只需更改每个Ball对象的位置/轨迹并调用repaint() 。 您可以在Ball类中使用可以改变方向的方法。

  4. 在Event Dispatch Thread上运行Swing应用程序。 您可以通过将main方法代码包装在SwingUtilities.invokeLater.. 。 请参见初始线程


这是一个例子

在此处输入图像描述

 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 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); } }); } }