当前位置: 首页 > 知识库问答 >
问题:

Java repaint()不调用paintComponent()

郎永福
2023-03-14

在试图制作一个非常简单的子弹地狱游戏来学习java时,我遇到了一个障碍: repaint()没有调用油漆组件()。

这是整个程序,目前只需将我每秒创建50次的图像绘制到JFrame上的JPanel上。

/*
 * 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编程有点陌生,可能只是缺少一些简单的东西。

编辑:问题已经通过将游戏面板更改为图形面板对象得到了解决。不幸的是,这也意味着我更大的乒乓球项目(这个项目有缺陷的绘图逻辑基本上是从那里复制的)只是奇迹般地工作,并且可能会因为某些代码的添加而不稳定。

共有1个答案

孙福
2023-03-14

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

  • 最重要的:你从来没有实例化过GraphicsPanel对象,也没有将它添加到任何东西中。在既没有渲染也没有创建的JPanel上,永远不会调用油漆组件(...)方法。为什么不让您的gamePanel变量成为GraphicsPanel对象,而不是JPanel对象呢?
  • 你永远不会改变你的计时器中的x和y,所以没有改变,就不会发生动画。
  • 另外,您正在调用JVM提供给您的Graphics对象的disuse,这是您永远不应该做的事情。这会破坏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();
            }
         }
      });
   }
}
 类似资料:
  • 问题内容: 我目前正在将GCM通知实施到我的应用中。 我遇到的问题是实现中的方法未被调用。我从GCM服务器收到的数据很好,因为它会自动生成一个通知(我希望使用该方法将其替换为我自己的通知),但是之后,我的所有日​​志调用都不会打印在日志中。 从服务器发送到GCM服务器的JSON AndroidManifest.xml(仅适用于GCM部分) GcmListenerService(只是一个快速打印,以

  • 对于我的程序,我目前希望使用open按钮打开JFileChooser并选择一个图像,然后在applet左侧的JPanel上绘制它,我知道该文件正在被检索,但当我重新绘制图形上下文时,什么也没有发生。提前谢了。

  • 问题内容: 我有一个自定义适配器,可显示订单列表中的每一行。 从Web服务查询新的订单列表之后,我想更新ListView的内容,因此我让Activity在调用notifyDataSetChanged()之前进行更新。 但是,从不调用OrderRowAdapter的getView()方法。ListView永远不会更新。 问题答案: 原来我不被叫的问题是因为它不可见。我的布局XML已经上与它的高度。因

  • 大家好,我在下面的链接中介绍了使用Python for Alexa的事实技能教程:https://github.com/alexa/skill-sample-python-fact 我的问题是Alexa只启动“启动请求” 但它不执行"GetNewFactIntent"的"IntentRequest" 正因为如此,只有调用名称在调用函数时有效,并且来自“GetNewFactIntent”的示例语句不

  • 问题内容: 我遵循以下示例:https : //code.google.com/p/mybatis/wiki/ResultHandlerExample 这是我的界面: 这是我的XML映射器 这段代码构成了我的DAO: 但是,永远不会调用结果处理程序。在这个例子中,我跟随人们说有同样的问题。那么如何使其工作呢?还是mybatis 3不支持结果处理程序? 问题答案: 我找到了答案。不幸的是,MyBat

  • 我创建了这个动画,通过停止动画进入 当SetAnimationDidStop的动画部分未被调用时。。。你能告诉我为什么,我哪里做错了吗? 这是一路动画: