obtener el ancho y alto de JPanel fuera de la clase

Resuelto asked hace 5 años • 1 respuestas

Así que creé una simulación simple donde los cuadrados se generan aleatoriamente con vectores aleatorios y rebotan en los bordes de la ventana.

Quería que tuviera en cuenta el tamaño de la ventana. De modo que si cambio las dimensiones de la ventana de 600x600 a 1200x600, los cuadrados rebotarán en el nuevo borde en lugar de 600x600.

Intenté hacer getWidth() getHeight() pero devolvía 0. Así que lo puse en el método Pain() (ya que se llama al cambiar el tamaño de la ventana) y guardé los valores de retorno como variables locales. Pero no puedo llamar a getjpWidth() desde la clase Rect.

Básicamente, lo que necesito es obtener una nueva dimensión de ventana en el método move() de la clase Rect.

No dude en señalar cualquier otro error y las cosas que se pueden hacer mejor. Soy nuevo en programación 2D (estudiando Informática)

Solicitud

import javax.swing.*;

public class Application {
    private Application(){
        //create a JFrame window
        JFrame frame = new JFrame("Moving Squares");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //add a JPanel
        GamePanel gamePanel = new GamePanel();
        frame.add(gamePanel);
        //pack the window around the content
        frame.pack();
        //center
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String args[]){
        new Application();
    }
}

Panel de juego

import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;

public class GamePanel extends JPanel implements Runnable{
    private int jpWidth=0, jpHeight=0;

    //set JPanel size
    private static final Dimension DESIRED_SIZE = new Dimension(600,600);
    @Override
    public Dimension getPreferredSize(){
        return DESIRED_SIZE;
    }

    //constructor
    GamePanel(){
        Thread t = new Thread(this);
        t.start();
    }

    private ArrayList <Rect> rect=new ArrayList<>();
    public void run(){
        for(int i=0; i<15; i++){
            rect.add(new Rect());
        }
        while(true){
            for(Rect rect:rect){
                rect.move();
            }
            //repaint still image for better frames
            //should be 100fps instead it's >144fps
            repaint();
            try{Thread.sleep(10);}
            catch(InterruptedException e){/**/};
            repaint();
            try{Thread.sleep(10);}
            catch(InterruptedException e){/**/};
            repaint();
            try{Thread.sleep(10);}
            catch(InterruptedException e){/**/};
        }
    }

    public void paint(Graphics g){
        Graphics2D g2d = (Graphics2D) g.create();
        jpWidth=getWidth();
        jpHeight=getHeight();
        g2d.setColor(Color.white);
        g2d.fillRect(0,0,jpWidth,jpHeight);
        for(Rect rect:rect) {
            g2d.setColor(Color.black);
            g2d.fillRect(rect.getXcord()-1, rect.getYcord()-1, rect.getWidth()+2, rect.getHeight()+2);
            g2d.setColor(Color.getHSBColor(rect.getR(), rect.getG(), rect.getB()));
            g2d.fillRect(rect.getXcord(), rect.getYcord(), rect.getWidth(), rect.getHeight());
        }
    }

    public int getJpWidth() {
        return jpWidth;
    }

    public int getJpHeight() {
        return jpHeight;
    }
}

recto

import java.util.Random;

public class Rect {
    //properties
    private int width=30, height=30;
    private int R, G, B;
    //movement
    private int xCord, yCord;
    private int xVector, yVector;
    private int xSlope, ySlope;

    public Rect(){
        Random rand = new Random();
        //random color
        R=rand.nextInt(255);
        G=rand.nextInt(255);
        B=rand.nextInt(255);

        //random spawn position
        xCord=rand.nextInt(600-width);
        yCord=rand.nextInt(600-height);

        //direction
        do{
            xVector=rand.nextInt(3) - 1;
            yVector=rand.nextInt(3) - 1;
        }while(xVector==0 || yVector==0);

        //slope
        do{
            xSlope=rand.nextInt(3);
            ySlope=rand.nextInt(3);
        }while(xSlope==0 || ySlope==0);
        xVector*=xSlope;
        yVector*=ySlope;
    }

    public void move(){
        //if(xCord>=//how to get screen width ? ){}
        if((xCord>=600-width) || (xCord<=0)){
            bounceX();
        }
        if((yCord>=600-height) || (yCord<=0)) {
            bounceY();
        }
        xCord+=xVector;
        yCord+=yVector;
    }

    public void bounceX(){
        xVector*=-1;
    }

    public void bounceY(){
        yVector*=-1;
    }

    public int getR() {
        return R;
    }

    public int getG() {
        return G;
    }

    public int getB() {
        return B;
    }

    public int getXcord() {
        return xCord;
    }

    public int getYcord() {
        return yCord;
    }

    public int getWidth(){
        return width;
    }

    public int getHeight(){
        return height;
    }
}
 avatar Jan 04 '19 01:01
Aceptado

Básicamente, lo que necesito es obtener una nueva dimensión de ventana en el método move() de la clase Rect.

No sé si es el mejor diseño, pero paso el "panel" como parámetro al método "move()" para que se pueda usar su ancho/alto.

Aquí hay un código antiguo que tengo por ahí que muestra este enfoque:

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.pack();
        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);
            ball.setSize(64, 64);
            balls.add( ball );
        }
    }

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

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

    @Override
    public Dimension getPreferredSize()
    {
        return new Dimension(800, 600);
    }

    public void startAnimation()
    {
        Timer timer = new Timer(1000/60, 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;
        }
    }
}

Además, tenga en cuenta que para la animación debería utilizar a Swing Timerpara programar la animación. Las actualizaciones de los componentes de Swing deben realizarse en el hilo de envío de eventos (EDT). Si bien no es probable que cause un problema con esta sencilla aplicación, es un buen hábito asegurarse de que se siga esta regla básica, de lo contrario, puede tener problemas aleatorios y nunca es fácil depurar un problema aleatorio.

camickr avatar Jan 03 '2019 19:01 camickr