在一个JFrame中同时处理两个JPanel [英] working on two JPanels simultaneously in a single JFrame
问题描述
我无法在网上找到合适的解决方案。所以我想在这里发帖。
现在让我们来解决我的问题。首先,我会解释我在做什么。然后我会解释我的问题。
我试图让两个球在JFrame中同时向不同的方向移动。 (基本上我认为就像连锁反应游戏一样,当你点击一个填充框时,球会同时向不同的方向移动)。
这里我创建两个(截至目前为止)两个球的JPanels,我试图在JFrame上同时移动。
这里是我试过的代码,
public class chainGraphics extends JPanel implements Runnable {
int oldX,oldY,newX,newY;
int changeX,changeY;
容器myPane;
public chainGraphics(int oldX,int oldY,int newX,int newY,Container myPane){
// TODO自动生成的构造函数存根
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; ((newY-oldY)== 0){
if(oldX< newX){
for(int i = oldX; i< newX; i ++){
b $ b System.out.println(hii123);
changeX = i;
尝试{
Thread.sleep(10);
} catch(InterruptedException e){
e.printStackTrace();
}
repaint();
else {
for(int i = oldX; i> newX; i - ){
changeX = i;
尝试{
Thread.sleep(10);
} catch(InterruptedException e){
e.printStackTrace();
}
repaint(); ((newX-oldX)== 0){
if(oldY
for(int i = oldY; i changeY = i;
尝试{
Thread.sleep(10);
} catch(InterruptedException e){
// TODO自动生成的catch块
e.printStackTrace();
}
repaint();
else {
for(int i = oldY; i> newY; i - ){
changeY = i;
尝试{
Thread.sleep(10);
} catch(InterruptedException e){
// TODO自动生成的catch块
e.printStackTrace();
}
repaint();
$ b public static void main(String [] args){
JFrame gui =新的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);
线程t1 =新线程(g);
t1.start();
线程t2 =新线程(g1);
t2.start();
尝试{
t1.join();
t2.join();
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
在这里,我看不到两个球同时移动。我猜想有一个问题。
我只能看到球沿y方向移动。 (但我希望两个球同时移动,因为我创建了两个线程)
我还注意到如果我先创建g1对象然后再创建g对象
那么球只会沿着x方向移动。
我认为Jframe只允许在一个JPanel上工作。 (并且我将JPanel添加到Frame彻底构造函数中)。所以JPanel最后添加到框架中,它允许在它上面工作。是这样吗 ?
如果是,我现在应该做什么。我的要求是我想在不同的方向同时移动球。
Thanks。
不,我想用两个线程绘制两个球
-
不要尝试将面板的两个实例添加到容器中。只需使用
Ball
对象的数据结构(我喜欢列表),并在paintComponent
方法中遍历它们。每个球都可以有一个drawBall(Graphics g)
方法,你可以在paintComponent
方法中调用,传入Graphics
context -
使用Swing
Timer
并忘记线程。Thread.sleep
不是Swing中的朋友。请参阅如何使用Swing Timers 在定时器中,只需更改每个Ball
对象的位置/轨迹,并调用重绘()
。您可以在Ball
类中添加方法,以改变方向。 调度线程。你可以通过将
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;
导入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;
私人列表< Ball>球;
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));
定时器定时器=新定时器(15,新的ActionListener(){
public void actionPerformed(ActionEvent e){
for(Ball ball:balls){
ball.animate();
}
repaint();
}
});
timer.start();
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
(球球:球){
ball.drawBall(g);
$ b @Override
public Dimension getPreferredSize(){
return new Dimension(D_W,D_H);
}
public class Ball {
int x = 0;
int y = 0; //当前球位置
int dx = 4; //增加球的x坐标
int dy = 4; //增加球的y坐标
int radius = 15; //球半径
public Ball(int x,int y){
this.x = x;
this.y = y; (Math.random()* 256),
(int)(Math.random()* 256),(int)(Math .random()* 256));
public void drawBall(Graphics g){
g.setColor(color);
g.fillOval(x - 半径,y - 半径,
半径* 2,半径* 2);
}
public void animate(){
if(x <0 || x> getWidth()){
dx = -dx;
}
if(y< 0 || y> getHeight()){
dy = -dy;
}
//调整球位置
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);
}
});
}
}
I m a newbie to java swing . And when trying with graphics i got stuck with this. I could'nt find a proper solution in web . So i thought of posting here .
so now lets come to my problem . First i will explain what i m trying to do . And then i will explain about my problem.
I m trying to make two balls move in different directions simultaneously in a JFrame . (Basically i thought of doing like chain Reaction game in which when you click on a filled box, the balls will move simultaneously in different directions ) .
Here i m creating two (as of now) JPanels for two balls which i m trying to move on a JFrame SIMULTANEOUSLY .
here is the code which i tried out ,
public class chainGraphics extends JPanel implements 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();
}
}
}
Here i couldnt see two balls moving simultaneously . There is a problem i guess. i could able to see ball moving along y direction only . (but i want both ball to move simutaneously, since i create two threads)
And i also noticed if i create g1 object first and then g object , then the ball moves along x direction only .
I think the Jframe allows to work on 1 JPanel only at a time . (And i am adding the JPanel to Frame thorough Constructor ) . so which ever JPanel is added lastly to frame ,it allows to work on it . is it so ? IF yes what should i do now .My requirement is i want to move balls simultaneously in different Directions. Thanks.
"No i am trying to draw two balls using two threads"
Don't try and add two instances of your panel to a container. Just Use a data structure (I prefer List) of
Ball
objects and loop through them in thepaintComponent
method. Each ball can have adrawBall(Graphics g)
method that you can call in thepaintComponent
method, passing to it theGraphics
contextUse a Swing
Timer
and forget about the threading.Thread.sleep
isn't your friend in Swing. See How to use Swing TimersIn the Timer, just change the locations/trajectory of locations of each
Ball
object and callrepaint()
. You can have methods in yourBall
class that will change direction.Run Swing apps on the Event Dispatch Thread. You can do so by wrapping your
main
method code in aSwingUtilities.invokeLater..
. See Initial Threads
Here's an example
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);
}
});
}
}
这篇关于在一个JFrame中同时处理两个JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!