簡體   English   中英

調用pack()后,JPanel getWidth()返回零

[英]JPanel getWidth() returns Zero, after invoking pack()

我相信我的代碼會描述我寫的內容,但是問題是,當我運行它時,我得到了臭名昭著的“ Animator”線程java.lang.IllegalArgumentException中的異常:寬度(0)和高度(0)不能為<= 0“錯誤。 我已經搜索了答案,但是還沒有找到原因。

package com.shparki.TowerDefense;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;

import javax.swing.JPanel;

public class GamePanel extends JPanel implements Runnable{

//==================== PROGRAM VARIABLES ====================//
    private static final int WIDTH = 300;
    private static final int HEIGHT = WIDTH / 16 * 9;
    private static final int SCALE = 4;

    private static final int TARGET_FPS = 45;
    private static final int PERIOD = 1000 / TARGET_FPS;

    private boolean debug = true;
    private volatile boolean running = false;
    private volatile boolean gameOver = false;
    private volatile boolean paused = false;

    private Thread animator;
    private TowerDefense frame;

    private double currentFPS;


//==================== PROGRAM METHODS ====================//
    public GamePanel(TowerDefense td){
        frame = td;

        setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

        setVisible(true);
    }
    public void addNotify(){
        super.addNotify();
        startGame();
    }
    public void startGame(){
        if (!running && animator == null){
            animator = new Thread(this, "Animator");
            animator.start();
        }
    }
    public void stopGame(){
        running = false;
    }
    public void run(){
        running = true;
        Long beforeTime, timeDiff, sleepTime;

        while(running){
            beforeTime = System.currentTimeMillis();

            update();
            render();
            paintScreen();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleepTime = PERIOD - timeDiff;
            if (sleepTime <= 0){
                sleepTime = 5L;
            }

            currentFPS = (1000 / ( timeDiff + sleepTime ));

            try{
                Thread.sleep(sleepTime);
            } catch (InterruptedException ex) { ex.printStackTrace(); }
        }
        System.exit(0);
    }

//==================== DRAWING METHODS ====================//
    private Graphics dbg;
    private Image dbImage;

    public void paintComponenet(Graphics g){
        super.paintComponent(g);
        if (dbImage != null){
            g.drawImage(dbImage, 0, 0, null);
        }
    }
    public void paintScreen(){
        Graphics g;
        try{
            g = this.getGraphics();
            if (g != null & dbImage != null){
                g.drawImage(dbImage, 0, 0, null);
            }
            Toolkit.getDefaultToolkit().sync();
            g.dispose();
        } catch (Exception ex) { System.out.println("Graphics context error: " + ex); }
    }
    public void doubleBuffer(){
        if (dbImage == null){
            dbImage = createImage(getWidth(), getHeight());
            if (dbImage == null){
                System.out.println("dbImage is null");
                return;
            } else {
                dbg = dbImage.getGraphics();
            }
        }
    }

//==================== UPDATE METHODS ====================//
    public void update(){

    }


//==================== RENDER METHODS ====================//
    public void render(){
        doubleBuffer();

        Graphics2D g2d = (Graphics2D) dbg;

        g2d.setColor(Color.BLACK);
        g2d.fillRect(0, 0, getWidth(), getHeight());
    }

}

這是我的框架課:

package com.shparki.TowerDefense;

import java.awt.BorderLayout;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

public class TowerDefense extends JFrame implements WindowListener{

    public TowerDefense(String name){
        super(name);
        setResizable(false);

        setLayout(new BorderLayout());
        add(new GamePanel(this), BorderLayout.CENTER);
        pack();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);

    }


    public void windowActivated(WindowEvent arg0) {  }
    public void windowClosed(WindowEvent arg0) {  }
    public void windowClosing(WindowEvent arg0) {  }
    public void windowDeactivated(WindowEvent arg0) {  }
    public void windowDeiconified(WindowEvent arg0) {  }
    public void windowIconified(WindowEvent arg0) {  }
    public void windowOpened(WindowEvent arg0) {  }

    public static void main(String[] args){
        new TowerDefense("Tower Defense Game");
    }

}

JFrame尚未打包,因此在GamePanel中要求高度和寬度

dbImage = createImage(getWidth(), getHeight());

導致JPanel尺寸為0x0

原因是在為組件設置了父組件之后,Swing幾乎立即調用addNotifystartGame所在的位置)。

您可以在調用startGame后顯式調用startGame

add(gamePanel, BorderLayout.CENTER);
pack();
gamePanel.startGame();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM