JPanel大小在开始时是未知的

时间:2015-05-13 22:31:27

标签: java swing jframe jpanel

当我从Square实例创建Board实例时,我尝试将窗口的大小分配给整数x和y。我没有这样做,因为它似乎在开始时大小为0.在Board.java的构造函数中,x和y不应该像-50一样现在最终结束。

Square.java:

package Square;

import javax.swing.*;

public class Square extends JFrame {

    public Square(){
        add(new Board());
        setSize(800, 800);
        setVisible(true);
    }

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

Board.java

package Square;

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

public class Board extends JPanel{
    int x,y;

    public Board(){
        x = width-50;
        y = height-50;
    }

    public int width = (int) getSize().getWidth();
    public int height = (int) getSize().getHeight();

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.fillRect(x,y, 100, 100);
    }
}

完整守则澄清: Square.java

package Square;

import javax.swing.*;

public class Square extends JFrame {

    public Square(){
        Board board = new Board();
        board.start();
        add(board);
        setTitle("Square");
        setSize(800, 800);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    public static void main(String[] args){
        Square square = new Square();
        square.setVisible(true);
        square.setLocation(2000, 150);
    }
}

Board.java

package Square;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Board extends JPanel implements ActionListener{

    Timer timer;
    int x, y;
    int velX = 0;
    int velY = 0;

    public Board(){
        setFocusable(true);
        timer = new Timer(1, this);
        addKeyListener(new TAdapter());
    }

    class TAdapter extends KeyAdapter{

        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();

            switch(keyCode){
                case KeyEvent.VK_ESCAPE: x = width()/2-50; y = height()/2-50; break;
                case KeyEvent.VK_RIGHT: velX = 1; break;
                case KeyEvent.VK_DOWN: velY = 1; break;
                case KeyEvent.VK_LEFT: velX = -1; break;
                case KeyEvent.VK_UP: velY = -1; break;
            }
        }

        public void keyReleased(KeyEvent e){
            velX = 0;
            velY = 0;
        }
    }
    public int width(){ return (int) getSize().getWidth();}
    public int height(){ return (int) getSize().getHeight();}

    public void start(){
        timer.setInitialDelay(100);
        timer.start();
        x = width()/2-50;
        y = height()/2-50;
    }



    @Override
    public void actionPerformed(ActionEvent e) {
        x += velX;
        y += velY;
        repaint();
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.fillRect(x,y, 100, 100);
    }
}

3 个答案:

答案 0 :(得分:5)

将计算放入paintComponent方法中。通常,您希望避免在paintComponent中使用会降低速度的代码,但这些调用不应该给予太多惩罚。此外,如果您的程序重新调整大小,您需要能够像这样重新计算出事物的大小:

Page<Person> findByNameOrAge(String name, int age,Pageable pageable);

但当然在你的真实节目中,你会想要避免&#34;魔法&#34;编号

另一个问题:请勿在您的JFrame上调用public void paintComponent(Graphics g){ super.paintComponent(g); int x = getWidth() - 50; int y = getHeight() - 50; g.fillRect(x, y, 100, 100); } 。相反,如果要指定硬件大小,请通过覆盖其setSize()方法在JPanel中执行此操作。这也将为您提供可用于计算的建议参数。

例如:

getPreferredSize()

另外,请查看我的this answer中的键绑定动画代码。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

@SuppressWarnings("serial")
public class DrawRect extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = PREF_W;
   private static final int DELTA = 50;
   private static final Color RECT_COLOR = Color.red;
   private static final int RECT_WIDTH = 100;
   private static final int TIMER_DELAY = 15;
   private int rectX = PREF_W - DELTA;
   private int rectY = PREF_H - DELTA;

   public DrawRect() {
      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(RECT_COLOR);
      g.fillRect(rectX, rectY, RECT_WIDTH, RECT_WIDTH);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         rectX--;
         rectY--;
         repaint();
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("DrawRect");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new DrawRect());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

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

答案 1 :(得分:2)

嘿,你的代码风格很糟糕,但我试着帮助:)。您无法获得未拉伸窗口的大小。首先,您的构造函数是错误的,您添加实际创建Board Obj的Board。调用Board的构造函数,它没有绘制父级,也没有设置x,y。尝试在构造函数中初始化变量。所以只需使用宽度和高度并填充构造函数中的值。接下来,通过将其父级大小传递给构造函数变量,告诉您的电路板其创建大小。 我想你试着学习java,这更优雅。此外,尝试在向其添加一些之前进行所有父修改。首先是setSize,添加一些Layout(Border / Flow / whatuwish),然后获取FramePane帧并添加你的Board组件。为了清楚起见,你不能得到例如Contructor中的父级和父级大小,因为您的主板Obj尚未创建和添加。如果你想要getParent()及其大小,创建Object将它添加到JFrame,然后你可以调用getParent()。getSize()。你得到0因为你的JPanel目前没有被绘制(在创建之前)。如果您希望获得父级大小,只需将JFrame参考传递给构造函数或其大小。另一个建议,不要在事物中创造事物,请记住你创建JPanel的代码作为第一个Obj ...以下是一些示例代码: 正方形:

public class Square extends JFrame {



    public static void main(String[] args){
       Square square = new  Square();
       square.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       Dimension d = new Dimension(800,800);
       square.setPreferredSize(d);
       square.setSize(d);


       //too much, every Jframe has BorderLayout enabled
       square.getContentPane().setLayout(new BorderLayout());
       square.getContentPane().add(new Board(square), BorderLayout.CENTER);
       square.pack();
       square.setVisible(true);

    }
}

板:

public class Board extends JPanel{
    int x,y;
    JFrame parent;

    public Board(JFrame parent){

         int width =  parent.getPreferredSize().width;
         int height = parent.getPreferredSize().height;
        x = width-50;
        y = height-50;
    }



    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.fillRect(x,y, 100, 100);
    }
}

答案 2 :(得分:1)

例如,在下一个EDT周期中,您可以通过使用SwingUtilities.invokeLater在面板变得可见后获取x和y值。