How to move two circles together in a JFrame from two different classes

为君一笑 提交于 2019-11-28 11:05:08

问题


I am trying to display the two circles moving together on a single frame through two different classes. But only one is shown moving at a time,even though value of "x" is changing continuously in class child1, paintComponent() is only taking the value of "x1" and showing the circle in moving from class child2.

If two separate frames are assigned to both the classes they works perfectly fine. Here is my code

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test13
{
    public static void main(String[] args)
    {
        child1 c1 = new child1();
        child2 c2 = new child2();
        JFrame f1 = new JFrame("Frame Test1");
        f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//passing a single JFrame to both methods as parameters    
        c1.cfunc1(f1);   
        c2.cfunc2(f1);   // but this line always hides the upper one
        f1.setSize(1000,700);
        f1.setVisible(true);
    }

}

class child1 extends JPanel implements ActionListener
{
    int x,y;
    int delay1;
    Timer timer1; //timer for 1st class constructor

    child1()
    {
        x=1;
        y=100;
        timer1 = new Timer(50,this);
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(x <= 500)
        {
            x += 1;
            y = 100;
            repaint();
        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.fillOval(x, y, 10, 10);
    }

    void cfunc1(JFrame f1)//passing JFrame as parameter 
    {
        child1 c1 = new child1();
        f1.add(c1);
        c1.timer1.start(); //timer started at the end of class1
    }
}  

class child2 extends JPanel implements ActionListener
{
    int x1,y1;
    int delay2;
    Timer timer2;

    child2()
    {
        x1 = 500;
        y1 = 100;
        timer2 = new Timer(50,this);//timer for 2nd class constructor
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        if(x1 <= 500)
        {
            x1 -= 1;
            y1 = 100;
            repaint();
        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.fillOval(x1, y1, 10, 10);
    }

    void cfunc2(JFrame f1)//passing JFrame as parameter
    {
        child2 c2 = new child2();
        f1.add(c2);
        c2.timer2.start();//timer started for 2nd class
    }
} 

回答1:


When two components are added to a single constraint of a BorderLayout (the default layout for a JFrame), only one is displayed.

The typical way to do this is not to design the custom painting in a JComponent (like JPanel) but instead to have them as simple classes which can paint(Graphics) or draw(Graphics) when requested to do so.

Then extend a single JComponent that iterates a list of the drawable components and paints each one.




回答2:


Don't create individual classes (child1, child2) for each object. What if you want 50 objects? Instead you create a class that accepts parameters that allows you to customize the object.

This example shows how you might:

  1. create a generic Ball class.
  2. uses a Swing Timer for animation of the balls
  3. create a panel that does custom painting by invoking the draw(...) method of each Ball.

Here is the code:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class BallAnimation4
{
    private static void createAndShowUI()
    {
        BallPanel panel = new BallPanel();

        JFrame frame = new JFrame("BallAnimation4");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( panel );
        frame.setSize(800, 600);
        frame.setLocationRelativeTo( null );
        //frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setVisible( true );

        panel.addBalls(5);
        panel.startAnimation();
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

class BallPanel extends JPanel implements ActionListener
{
    private ArrayList<Ball> balls = new ArrayList<Ball>();

    public BallPanel()
    {
        setLayout( null );
        setBackground( Color.BLACK );
    }

    public void addBalls(int ballCount)
    {
        Random random = new Random();

        for (int i = 0; i < ballCount; i++)
        {
            Ball ball = new Ball();
            ball.setRandomColor(true);
            ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
            ball.setMoveRate(32, 32, 1, 1, true);
//          ball.setMoveRate(16, 16, 1, 1, true);
            ball.setSize(32, 32);
            balls.add( ball );
        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        for (Ball ball: balls)
        {
            ball.draw(g);
        }
    }

    public void startAnimation()
    {
        Timer timer = new Timer(75, this);
        timer.start();
    }

    public void actionPerformed(ActionEvent e)
    {
        move();
        repaint();
    }

    private void move()
    {
        for (Ball ball : balls)
        {
            ball.move(this);
        }
    }


    class Ball
    {
        public Color color = Color.BLACK;

        public int x = 0;
        public int y = 0;
        public int width  = 1;
        public int height = 1;

        private int moveX = 1;
        private int moveY = 1;
        private int directionX = 1;
        private int directionY = 1;
        private int xScale = moveX;
        private int yScale = moveY;

        private boolean randomMove = false;
        private boolean randomColor = false;
        private Random myRand = null;

        public Ball()
        {
            myRand = new Random();
            setRandomColor(randomColor);
        }

        public void move(JPanel parent)
        {
            int iRight = parent.getSize().width;
            int iBottom = parent.getSize().height;

            x += 5 + (xScale * directionX);
            y += 5 + (yScale * directionY);

            if (x <= 0)
            {
                x = 0;
                directionX *= (-1);
                xScale = randomMove ? myRand.nextInt(moveX) : moveX;
                if (randomColor) setRandomColor(randomColor);
            }

            if (x >= iRight - width)
            {
                x = iRight - width;
                directionX *= (-1);
                xScale = randomMove ? myRand.nextInt(moveX) : moveX;
                if (randomColor) setRandomColor(randomColor);
            }

            if (y <= 0)
            {
                y = 0;
                directionY *= (-1);
                yScale = randomMove ? myRand.nextInt(moveY) : moveY;
                if (randomColor) setRandomColor(randomColor);
            }

            if (y >= iBottom - height)
            {
                y = iBottom - height;
                directionY *= (-1);
                yScale = randomMove ? myRand.nextInt(moveY) : moveY;
                if (randomColor) setRandomColor(randomColor);
            }
        }

        public void draw(Graphics g)
        {
            g.setColor(color);
            g.fillOval(x, y, width, height);
        }

        public void setColor(Color c)
        {
            color = c;
        }

        public void setLocation(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
        {
            this.moveX = xMove;
            this.moveY = yMove;
            directionX  = xDir;
            directionY  = yDir;
            randomMove  = randMove;
        }

        public void setRandomColor(boolean randomColor)
        {
            this.randomColor = randomColor;

            switch (myRand.nextInt(3))
            {
                case 0:  color = Color.BLUE;
                         break;
                case 1:  color = Color.GREEN;
                         break;
                case 2:  color = Color.RED;
                         break;
                default: color = Color.BLACK;
                         break;
            }
        }

        public void setSize(int width, int height)
        {
            this.width  = width;
            this.height = height;
        }
    }
}

Normally you wouldn't make the classes static.



来源:https://stackoverflow.com/questions/28859324/how-to-move-two-circles-together-in-a-jframe-from-two-different-classes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!