在单个 JFrame 中同时处理两个 JPanel [英] working on two JPanels simultaneously in a single JFrame

查看:31
本文介绍了在单个 JFrame 中同时处理两个 JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 java swing 的新手.尝试使用图形时,我遇到了这个问题.我在 web 中找不到合适的解决方案.所以我想在这里发帖.

现在让我们来解决我的问题.首先,我将解释我正在尝试做什么.然后我会解释我的问题.

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

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

这是我试过的代码,

公共类chainGraphics扩展JPanel实现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);}公共无效paintComponent(图形g){//super.paintComponent(g);System.out.println("hj");g.drawOval(changeX,changeY, 40, 40);}@覆盖公共无效运行(){System.out.println("hii");更改 X = 旧 X;changeY = oldY;if((newY-oldY)==0){如果(旧X<新X){for(int i=oldX;i<newX;i++){System.out.println("hii123");改变X = i;尝试 {线程睡眠(10);} catch (InterruptedException e) {e.printStackTrace();}重绘();}}别的    {for(int i=oldX;i>newX;i--){改变X=i;尝试 {线程睡眠(10);} catch (InterruptedException e) {e.printStackTrace();}重绘();}}}if((newX-oldX)==0){如果(旧Y<新Y){for(int i=oldY;i<newY;i++){改变Y=i;尝试 {线程睡眠(10);} catch (InterruptedException e) {//TODO 自动生成的 catch 块e.printStackTrace();}重绘();}}别的    {for(int i=oldY;i>newY;i--){改变Y=i;尝试 {线程睡眠(10);} catch (InterruptedException e) {//TODO 自动生成的 catch 块e.printStackTrace();}重绘();}}}}公共静态无效主(字符串 [] args){JFrame gui = new JFrame();gui.setTitle("连锁反应;-)");gui.setSize(650,650);gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);gui.setLocationRelativeTo(null);gui.setVisible(true);容器窗格 = 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 只允许一次在 1 个 JPanel 上工作.(我正在将 JPanel 添加到 Frame 彻底的构造函数).因此,最后将哪个 JPanel 添加到框架中,它允许对其进行处理.是这样吗 ?如果是,我现在应该怎么做.我的要求是我想在不同的方向同时移动球.谢谢.

解决方案

不,我想用两条线画两个球"

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

  2. 使用 Swing Timer 而忘记线程.Thread.sleep 不是您在 Swing 中的朋友.请参阅如何使用摆动计时器>

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

  4. 在事件调度线程上运行 Swing 应用程序.您可以通过将 main 方法代码包装在 SwingUtilities.invokeLater.. 中来实现.请参阅初始线程

<小时>

这是一个例子

import java.awt.Color;导入 java.awt.Dimension;导入 java.awt.Graphics;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 java.util.ArrayList;导入 java.util.List;导入 java.util.Random;导入 javax.swing.JFrame;导入 javax.swing.JPanel;导入 javax.swing.SwingUtilities;导入 javax.swing.Timer;公共类 MoveBalls 扩展 JPanel {私有静态最终 int D_W = 500;私有静态最终 int D_H = 300;私人名单<球>球;公共移动球(){随机 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 = new Timer(15, new ActionListener() {public void actionPerformed(ActionEvent e) {对于(球球:球){球.animate();}重绘();}});定时器开始();}@覆盖受保护的无效paintComponent(图形g){super.paintComponent(g);对于(球球:球){ball.drawBall(g);}}@覆盖公共维度 getPreferredSize() {返回新维度(D_W,D_H);}公共课球{整数 x = 0;int y = 0;//当前球的位置int dx = 4;//增加球的 x 坐标int dy = 4;//增加球的 y 坐标整数半径 = 15;//球半径公共球(int x,int y){this.x = x;this.y = y;}颜色颜色 = 新颜色((int) (Math.random() * 256),(int) (Math.random() * 256), (int) (Math.random() * 256));公共无效drawBall(图形g){g.setColor(颜色);g.fillOval(x - 半径,y - 半径,半径*2,半径*2);}公共无效动画(){if (x <0 || x > getWidth()) {dx = -dx;}if (y < 0 || y > getHeight()) {dy = -dy;}//调整球位置x += dx;y += dy;}}公共静态无效主(字符串 [] args){SwingUtilities.invokeLater(new Runnable() {公共无效运行(){JFrame frame = new JFrame();frame.add(new MoveBalls());frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);框架.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"

  1. 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 the paintComponent method. Each ball can have a drawBall(Graphics g) method that you can call in the paintComponent method, passing to it the Graphics context

  2. Use a Swing Timer and forget about the threading. Thread.sleep isn't your friend in Swing. See How to use Swing Timers

  3. In the Timer, just change the locations/trajectory of locations of each Ball object and call repaint(). You can have methods in your Ball class that will change direction.

  4. Run Swing apps on the Event Dispatch Thread. You can do so by wrapping your main method code in a SwingUtilities.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆