【问题标题】:Java repaint() not calling paintComponent()Java repaint() 不调用paintComponent()
【发布时间】:2015-03-30 15:10:08
【问题描述】:

为了制作一个非常简单的弹幕游戏来学习 Java,我遇到了一个障碍:repaint() 没有调用 paintComponent()。

这是整个程序,现在它只是将我每秒创建 50 次的图像绘制到 JPanel 上,该 JPanel 位于 JFrame 上。

/*
 * Bullet hell, by Nematodes
 */

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class bulletHell extends JFrame
{
    private static final long serialVersionUID = 0L;
    JPanel gamePanel = new JPanel();
    int gameTimerDelay = 20;
    int x, y = 0;
    BufferedImage lightOrb;
    javax.swing.Timer gameTimer;

    public static void main(String[] args)
    {
        bulletHell createFrame = new bulletHell();
        createFrame.frameConstructor();
    }

    public void frameConstructor()
    {
        // Construct frame and frame components
        setTitle("Bullet hell");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        getContentPane().setLayout(new GridBagLayout());
        setVisible(true);

        GridBagConstraints gridConstraints;

        gridConstraints = new GridBagConstraints();
        gridConstraints.gridx = 0;
        gridConstraints.gridy = 0;
        gamePanel.setBackground(Color.BLACK);
        gamePanel.setPreferredSize(new Dimension(700, 700));
        getContentPane().add(gamePanel, gridConstraints);

        pack();

        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((int) (0.5 * (screenSize.width - getWidth())),
                 (int) (0.5 * (screenSize.height - getHeight())), getWidth(), getHeight());

        try
        {
            lightOrb = ImageIO.read(new File("C:/Users/Owner/Downloads/orb.bmp"));
        }
        catch(IOException e)
        {
            System.out.println("An issue occurred while trying to read orb.bmp");
        }

        // Start timer that draws game objects 50 times per second (50 FPS)
        gameTimer = new javax.swing.Timer(gameTimerDelay, gameTimerAction);
        gameTimer.setInitialDelay(0);
        gameTimer.start();
    }

    ActionListener gameTimerAction = new ActionListener()
    {
        public void actionPerformed(ActionEvent e)
        {
            repaint();
        }
    };

    class GraphicsPanel extends JPanel
    {
        public GraphicsPanel()
        {

        }

        // Draw all of the components
        @Override
        public void paintComponent(Graphics g)
        {
            Graphics2D g2D = (Graphics2D) g;
            super.paintComponent(g2D);
            g2D.drawImage(lightOrb, x, y, this);
            g2D.dispose();
        }
    }
}

在使用断点和 println 方法进行一些调试后,我可以确认正在读取正确的图像,gameTimerAction 中的计时器每秒被调用 50 次,并且 repaint() 根本没有调用 paintComponent()。

我对 Java 编程有点陌生,可能只是缺少一些简单的东西。

编辑:问题已通过将 gamePanel 更改为 GraphicsPanel 对象来解决。不幸的是,这也意味着我的更大的 pong 项目(该项目的有缺陷的绘图逻辑基本上是从该项目中复制而来的)只能奇迹般地工作,并且在添加某些代码时可能会不稳定。

【问题讨论】:

    标签: java swing paintcomponent repaint paintevent


    【解决方案1】:

    我可以立即看到几个问题:

    • 最重要的:您永远不会实例化 GraphicsPanel 对象,也不会将其添加到任何东西中。 paintComponent(...) 方法永远不会在既未呈现也未创建的 JPanel 上调用。为什么不将您的 gamePanel 变量设为 GraphicsPanel 对象而不是 JPanel 对象?
    • 您永远不会更改 Timer 中的 x 和 y,因此如果不更改,则不会出现动画。
    • 另外,您正在对 JVM 提供给您的 Graphics 对象调用 dispose,这是您永远不应该做的事情。这会破坏 Swing 绘制链,使您的 GUI 图形不稳定。

    坚持下去,你会成功的。

    例如:

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class BulletExample extends JPanel {
       public static final String IMG_PATH = "http://www.i2clipart.com/cliparts/f/0/5/8/clipart-blue-circle-f058.png";
       private static final int PREF_W = 700;
       private static final int PREF_H = PREF_W;
       private static final int TIMER_DELAY = 20;
       private BufferedImage bullet;
       private int bulletX;
       private int bulletY;
    
       public BulletExample() throws IOException {
          URL imgUrl = new URL(IMG_PATH);
          bullet = ImageIO.read(imgUrl);
          new Timer(TIMER_DELAY, new BulletListener()).start();
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          if (bullet != null) {
             g.drawImage(bullet, bulletX, bulletY, this);
          }
       }
    
       @Override
       public Dimension getPreferredSize() {
          if (isPreferredSizeSet()) {
             return super.getPreferredSize();
          }
          return new Dimension(PREF_W, PREF_H);
       }
    
       private class BulletListener implements ActionListener {
          @Override
          public void actionPerformed(ActionEvent e) {
             bulletX++;
             bulletY++;
             repaint();
          }
       }
    
       private static void createAndShowGui() throws IOException {
    
          // create the drawing JPanel
          BulletExample mainPanel = new BulletExample();
    
          JFrame frame = new JFrame("BulletExample");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    
          // add it to the JFrame
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                try {
                   createAndShowGui();
                } catch (IOException e) {
                   e.printStackTrace();
                }
             }
          });
       }
    }
    

    【讨论】:

    • 感谢您的帮助!初始化 GraphicsPanel 对象而不是 JPanel 以在允许调用的 paintComponent 上渲染图像,从而绘制图像。
    • (没有足够快地编辑我之前的评论)我还没有计划动画,但也许我可以从你的代码示例中学到一些东西
    猜你喜欢
    • 1970-01-01
    • 2017-01-03
    • 1970-01-01
    • 2015-08-26
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多