【问题标题】:Image wont draw in Java图像不会在 Java 中绘制
【发布时间】:2015-11-05 21:28:24
【问题描述】:

所以我试图将图像绘制到 JFrame 上,并且我使用默认工具包作为图像观察器,但是每次运行项目时它都不会绘制图像,但是它会绘制和移动(成功) 我测试的其他形状。

private class Painter extends JPanel implements ImageObserver {

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    Toolkit tk = Toolkit.getDefaultToolkit();
    Image player = tk.createImage("player.jpg");
    tk.prepareImage(player, 50, 50, rootPane);        
    g.setColor(Color.red);
   // g.drawRect(x, y, 50, 50); 
    g.drawImage(player, 200, 200, this);
    window.repaint();            
    }
}

【问题讨论】:

  • 图片在哪里? createImage 将在当前工作目录中的文件系统中查找名为“player.jpg”的文件
  • 图片与包位于同一文件夹内
  • 假设您的意思是图像与类在同一个包中或直接在源内部,那么,您的问题就来了。您需要使用Class#getResource 获取资源的URL,然后您可以从中加载图像。您可以使用ImageIO.read(getClass().getResource("player.jpg")) 加载图像,但已经说明,您不应该在paint 方法中执行此操作
  • private class Painter extends JPanel implements ImageObserver { implements ImageObserver 部分是多余的,因为每个 java.awt.ComponentJComponentJPanel 扩展)都已经实现了 ImageObserver ..

标签: java image swing jpanel


【解决方案1】:

您的paintComponent 方法不应该做任何事情。

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.red);
        // g.drawRect(x, y, 50, 50);
        g.drawImage(player, 200, 200, this);
    }

工具包和图像行需要在 Painter 构造函数中。类名应以大写字母开头。

根据评论编辑:

您编写的代码如下所示:

private Image player;

public Painter() throws Exception {
    player = ImageIO.read(getClass().getResource("player.jpg"));
}

player.jpg 需要与源代码在同一目录中。否则,您的图像目录需要位于 Java 应用程序的类路径中。

这是一个完整、简单的 Swing 应用程序,用于在 JPanel 上绘制图像。

package com.ggl.testing;

import java.awt.Graphics;
import java.awt.Image;
import java.io.IOException;

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

public class MyPanel extends JPanel {

    private static final long serialVersionUID = -9008812738915944216L;

    private static JFrame frame;
    private static MyPanel panel;
    private static Image image;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                image = getImage();
                frame = new JFrame();
                panel = new MyPanel();
                frame.setSize(500, 500);
                frame.add(panel);
                frame.setVisible(true);
            }
        });
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 100, 100, MyPanel.this);
    }

    private static Image getImage() {
        Image image = null;
        try {
            image = ImageIO.read(MyPanel.class.getResource("maze.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }
}

将 maze.jpg 更改为您的图像,并将图像放在与此示例代码相同的目录中。

【讨论】:

  • 能否详细说明将工具包和图像行放入构造函数中?
  • @Tristan:我修改了答案。
【解决方案2】:
  1. 不要在绘画方法中执行 I/O。绘画方法仅用于绘画。
  2. 不要在绘画方法中调用 repaint()。这将导致无限循环。

使用 ImageIO 在类的构造函数中将图像读入类的变量中,以便在绘制图像时可以使用图像。如果找不到图像,ImageIO 将生成一条消息。

【讨论】:

    【解决方案3】:

    对于任何感兴趣的人来说,最终的代码都是这样的。之前没有包括动作监听器,因为它与问题几乎无关。之所以包含最后一个 sn-p,即公共绘画,是因为无法从静态 main 方法内部调用动作侦听器。这个子类最初是包含所有 window.* 行的,但导致创建的窗口数无限,所以当它被移动到主时,新的绘画调用必须封装在一个受控循环中,并且在主方法之外。 特别感谢所有帮助我的人,尤其是 Gilbert Le Blanc

    package painting;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.KeyEvent;
    import java.awt.event.*;
    import java.io.*;
    import javax.imageio.ImageIO;
    
    
    /**
     *
     * @author tt700
     */
    public class Painting extends JPanel {
        // declaring variables that control movement, show the frame, and make the picture
        int x =50, y =50, counter = 0;
        private static JFrame window = new JFrame("Paint a Picture");
        private static Painting canvas;
        private static Image player;
    
    
    // main method
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable(){
        @Override
        public void run(){    
        JLabel title = new JLabel("Making a picture frame");
        window.add(title, BorderLayout.NORTH);
        canvas = new Painting();
        window.add(canvas);
        player = getImage("player.jpg");
        window.setVisible(true);
        window.setSize(300,300);
        window.setForeground(Color.red);
    
        }
       });
    }
    
    @Override
    // the method that does all the painting
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(player, x, y, Painting.this);
    }
    
    // the method that gets a desired image and makes it displayable, with arguments it can be used to swap pictures easily
    private static Image getImage(String imagePath){
        Image player = null;
     try{
        player = ImageIO.read(Painting.class.getResource(imagePath));
            }catch(IOException e){
                e.printStackTrace();
            }
          return player; 
    }
    // the class that controls movement of the picture
    public class movement implements KeyListener{   
    
        @Override
        public void keyTyped(KeyEvent e) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    
        @Override
        // the method that listens to which keys are pressed and acts accordingly
        public void keyPressed(KeyEvent e) {
            if(e.getKeyCode() == KeyEvent.VK_RIGHT){                
            x += 5;                
            window.repaint();
        }
        else if(e.getKeyCode() == KeyEvent.VK_LEFT){
            x -= 5;
            window.repaint();
        }
        else if(e.getKeyCode() == KeyEvent.VK_UP){
            y -= 5;
            window.repaint();
        }
        else if(e.getKeyCode() == KeyEvent.VK_DOWN){
            y += 5;
            window.repaint();
        }
        }
    
        @Override
        public void keyReleased(KeyEvent e) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }       
    }
    
    // the subclass that adds a key listener to the proper component, created since action listeners can't be called in static methods (main)
    public Painting(){
        do{
        counter = 1;
        window.addKeyListener(new movement());
        }while(counter < 1);
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-28
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多