【问题标题】:paint() method would not draw on JPanelpaint() 方法不会在 JPanel 上绘制
【发布时间】:2017-06-27 23:34:08
【问题描述】:

我尝试了一些在 java 中绘图的源代码,它们工作正常,但是当我尝试自己制作一个时,我无法让 paint(Grahpics g) 方法工作!我再次查看了我拥有的代码并检查了 Oracle 页面中的一些教程,但我似乎无法知道为什么它不起作用。 有人可以检查一下并告诉我这里出了什么问题吗?

主要方法: 公共类主

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

板:

import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class board implements ActionListener
{
    private JFrame f = new JFrame("Speedy");
    private JPanel gamePanel = new JPanel();


    private Image bg = new ImageIcon(this.getClass().getResource("road.png")).getImage();
    private Timer t;


    private car myCar = new car();


    public board()
    {
        t = new Timer(50,this);
        t.start();


        gamePanel.setSize(600,400);
        gamePanel.setDoubleBuffered(true);
        gamePanel.setFocusable(true);
        gamePanel.addKeyListener(new TAdapter());

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(gamePanel,BorderLayout.CENTER);
        //f.addKeyListener(new TAdapter());
        f.setBounds(200,100,600,400);
        f.setVisible(true);
        f.revalidate();
        f.repaint();

    }




    public void paint(Graphics g) {
        gamePanel.paint(g);

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(bg,0,0,null);
        g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);

        System.out.println("Painted");

        g.dispose();
    }



    public void actionPerformed(ActionEvent e) 
    {
        gamePanel.repaint();
        //System.out.println("Painting..");
    }





    private class TAdapter extends KeyAdapter {

        public void keyReleased(KeyEvent e) {}

        public void keyPressed(KeyEvent e)  
        {
            myCar.keyPressed(e);
            System.out.println("You pressed: "+e);
        }
    }

}

汽车.java:

    import java.awt.Image;
    import java.awt.event.KeyEvent;
    import java.util.ArrayList;

    import javax.swing.ImageIcon

;



public class car 
{

    private Image image;
    public int xPos,yPos;

    public car()
    {
        image = new ImageIcon(this.getClass().getResource("car.png")).getImage();
        xPos = 300;
        yPos = 200;
        System.out.println(image.getWidth(null));
    }



    public Image getImg() {return image;}


    public void move() {}


    public void keyPressed(KeyEvent e) 
    {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) xPos -= 1;
        if (key == KeyEvent.VK_RIGHT)xPos += 1;
        if (key == KeyEvent.VK_UP)   yPos -= 1;
        if (key == KeyEvent.VK_DOWN) yPos += 1;
    }

}

没有错误,它显示了正确的图像宽度,还有计时器触发ActionListenerKeyListener 也在工作,但图像不会绘制! paint(Graphics g) 方法只是不想被触发! 谷歌搜索没有帮助..我认为这将是一个常见问题,但没有人遇到我的问题,所有解决方案都失败了。 请帮忙? 如果有人能解释一下,将不胜感激!

【问题讨论】:

    标签: java swing draw drawing2d


    【解决方案1】:

    您的 Board 类没有扩展 JPanel 类。因此,Swing 永远不会调用 paint() 方法。 另外,gamePanel.repaint() 语句只会执行默认的JPanel paint() 方法gamePanel。相反,您希望执行覆盖的 paint 方法,因此可能需要这样做:

    public class Board extends JPanel implements ActionListener {
       ....
        public void paint(Graphics g) {
           this.paint(g);
    
           Graphics2D g2d = (Graphics2D)g;
           g2d.drawImage(bg,0,0,null);
           g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);
    
           System.out.println("Painted");
    
           g2d.dispose();
        }
        ....
    }
    

    用这个替换你的操作功能:

    public void actionPerformed(ActionEvent e) {
       this.repaint();
    }
    

    替代解决方案: 如果您不希望您的Board 类扩展JPanel,您还可以在初始化时重写gamePanelpaint() 方法。

    gamePanel = new JPanel() {
       @Override
       public void paint(Graphics g) {
           this.paint(g);
    
           Graphics2D g2d = (Graphics2D)g;
           g2d.drawImage(bg,0,0,null);
           g2d.drawImage(myCar.getImg(), myCar.xPos, myCar.yPos, null);
    
           g2d.dispose();
       }
    };
    

    但是,我会推荐第一个解决方案,而不是 anonymous classes 这个解决方案。

    【讨论】:

    • 但我做了gamePanel.repaint(),这不应该触发它吗?我不能在当前的 JPanel 上触发它吗?
    • 不,gamePanelJPanel 的一个实例,调用gamePanel.repaint() 只会触发原来的JPanel paint() 方法。但是,您想触发 your paint 方法,该方法具有绘制汽车的实现。我已经更新了我的答案。
    • 是否可以在当前代码中为新的JPanel实例设置当前绘制方法?还是我必须为其创建一个新对象?
    • 另外,根据您所说的,paint(Graphics g) 方法实际上是对原始 JPanel 对象的覆盖?
    • 是的,您可以在初始化时覆盖gamePanelpaint 方法。关于你的第二个问题,paint 方法应该覆盖默认的paint 方法以扩展默认功能。
    【解决方案2】:

    当您在某个容器上调用 repaint 时,Swing 会查看该容器中的所有组件并调用它们的 paint 方法。

    但是,您的 board 类(顺便说一下,您应该称它为 Board。类名应始终以大写字母开头)不是 JFrame 的组件。当您调用repaint 时,Swing 将尝试调用JPanel 的paint 方法,它是JFrame 的一个组件。但是您没有覆盖该方法。您刚刚向您的board 添加了一个paint 方法,而board 不是JFrame 的一个组件。

    因此,通常您应该创建一个扩展JPanel 或其他组件的类,然后将该类的当前对象作为组件添加到JFrame。这样,paint 方法将在重新绘制 JFrame 时被调用。

    【讨论】:

      【解决方案3】:

      您的“主”类 (board) 应该扩展 JPanel 以按预期工作。 以你的方式,paint 永远不会被调用。它就像任何普通的自写函数一样。

      如果你想保持原样,你可以这样做:

      gamePanel = new JPanel() 
      {
          @Override
          public void paint(Graphics g) 
          {
              //your code here
          }
      };
      

      请记住,Class 名称应以大写字母开头。它不会产生任何错误,但它是一个命名约定,您可以在此处看到: http://www.oracle.com/technetwork/java/codeconventions-135099.html

      【讨论】:

        猜你喜欢
        • 2018-08-23
        • 2010-10-04
        • 2014-10-02
        • 2013-11-29
        • 1970-01-01
        • 2021-04-14
        • 1970-01-01
        • 2016-07-01
        相关资源
        最近更新 更多