某些图像无法立即绘制

Posted

技术标签:

【中文标题】某些图像无法立即绘制【英文标题】:Some Image couldn't draw immediately 【发布时间】:2017-01-31 18:52:41 【问题描述】:

我是 Java GUI 编程的新手。以下代码是我简化的问题。

单击面板时会绘制两个图像。一个是使用drawVrImage() 方法绘制的Red Box,另一个是使用drawRealImage() 方法绘制的Red Star。所有图像中的两个是沿着增加的行绘制的。

这是结果图片:

点击5次后显示。但问题是drawRealImage() 仅绘制了 4 次图像,即使它被调用了 5 次。第一个红盒子在哪里?为什么BufferedImage 不能显示第一个红框。

GUI 类仅用于加载图像。所有图像都已加载并在启动时放置HashMap。所以,我认为图像加载(Qwirkle.getImage())没有问题。我认为缓冲图像没有 Image Observer 是问题。但是如果真的有问题。如何画第二个红框。

供您参考。这里是代码解释。 BIsource 类有一个 BuffedImage。当我点击UserPanelBufferedImage in BIsource 获取其图形并绘制图像。完成绘制图像后,UserPanel 从 BIsource 获取该图像。并调用reapint() 方法。 UserPanel 中的 paintCompent() 方法仅适用于从 BIsource Instance 绘制缓冲图像。

我该如何解决这个问题?

用户面板类

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class UserPanel extends JPanel implements MouseListener 

    private BIsource draw;
    private BufferedImage bi;
    
    public UserPanel() 

        this.draw = new BIsource();
        this.bi = draw.getBI();
        this.addMouseListener(this);
    

    @Override
    protected void paintComponent(Graphics g) 
        // TODO Auto-generated method stub
        g.drawImage(bi, 0, 0, this);
    

    @Override
    public void mouseClicked(MouseEvent e) 
        this.draw.drawVrImage();
        this.draw.drawRealImage();
        this.draw.incIndex();
        bi = this.draw.getBI();
        this.repaint();
    

    class BIsource 

        private BufferedImage biCanvas;

        private HashMap<String, BufferedImage> imageMap;

        private int index = 0;

        public BIsource() 

            // biCanvas Declaration
            biCanvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics g = biCanvas.createGraphics();
            g.setColor(Color.blue);
            g.fillRect(0, 0, 500, 500);
            g.dispose();

            imageMap = new HashMap<>();
            this.createVrImage();
        

        private void createVrImage() 
            BufferedImage vrImage = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics g = vrImage.createGraphics();
            g.setColor(Color.red);
            g.fillRect(0, 0, 50, 48);
            g.dispose();

            this.imageMap.put("TEST IMAGE", vrImage);
        

        public BufferedImage getBI() 
            return this.biCanvas;
        

        public void drawVrImage() 
            Graphics g = biCanvas.createGraphics();
            g.drawImage(this.imageMap.get("TEST IMAGE"), 0, index * 50, null);
            g.dispose();
        

        public void drawRealImage() 
            Graphics g = biCanvas.getGraphics();
            g.drawImage(Qwirkle.getImage("RED STAR"), 200, index * 50, null);
            g.dispose();
        

        public void incIndex() 
            index += 1;
        
    
    
    public static void main(String[] args) 

        Qwirkle.loadQwirkleImage();

        JFrame mainFrame = new JFrame("Test Frame");
        mainFrame.setLayout(null);
        mainFrame.setSize(500, 500);
        mainFrame.setVisible(true);
        mainFrame.setBackground(Color.black);
        mainFrame.setLocation(800, 400);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        UserPanel userPanel = new UserPanel();
        mainFrame.add(userPanel);
        userPanel.setSize(500, 500);
        userPanel.setVisible(true);

    
    

    @Override
    public void mouseEntered(MouseEvent e) 

    @Override
    public void mouseExited(MouseEvent e) 

    @Override
    public void mousePressed(MouseEvent e) 

    @Override
    public void mouseReleased(MouseEvent e) 

Qwirkle 类

import java.awt.Image;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Random;

public class Qwirkle implements Serializable 

    private static HashMap<String, Image> qwirkleImages;

    // static initialize
    static 

    

    public enum Color 
        CYAN, GREEN, ORANGE, PURPLE, RED, YELLOW
    

    public enum Shape 
        CIRCLE, CLOVER, DIAMOND, RECTANGLE, STAR, URCHIN
    

    private final Color color;
    private final Shape shape;
    private final int index;

    public Qwirkle(Color color, Shape shape, int index) 

        this.color = color;
        this.shape = shape;
        this.index = index;
    

    public static void loadQwirkleImage() 

        if (Qwirkle.qwirkleImages == null) 
            Qwirkle.qwirkleImages = new HashMap<>();
                String key;
                try 
                    for (Qwirkle.Color color : Qwirkle.Color.values()) 
                        for (Qwirkle.Shape shape : Qwirkle.Shape.values()) 
                            key = new String(color.toString() + " " + shape.toString());
                            Qwirkle.qwirkleImages.put(key, GUI.loadImage(key + ".jpg"));
                        
                    
                 catch (Exception e) 
                    e.printStackTrace();
                
         else 
            System.err.println("Already Loading all Qwirkle Image");
        
    

    public static Image getImage(String key) 
        return qwirkleImages.get(key);
    

    synchronized public String getKey() 
        return new String(color.toString() + " " + shape.toString());
    

    @Override
    public String toString() 
        return new String(color.toString() + " " + shape.toString() + " " + index);
    

    public Color getColor() 
        return color;
    

    public Shape getShape() 
        return shape;
    
    
    

【问题讨论】:

如果调试没有立竿见影的帮助,请创建minimal reproducible example 关注问题所在。在您的示例中,通过URL 访问发布的图像,如here 所示;使用合成图像,如图here;或者使用UIManager图标,如图here。 您的程序没有 qwirkle 并且只有另一个图像可以正常工作 - 我建议您不要使用静态;删除所有静态(并同步,除非你真的知道你需要它(不仅仅是为了好玩) @gpasch 这是固定代码。我希望你知道这不是家庭作业和作业。 【参考方案1】:

终于有答案了。我更改了 HashMap 对象。我将 HashMap 用于放置图像类。但现在我将 BufferedImage 存储在 HashMap 中。它运作良好。当我第一次点击时,它立即绘制了一个红星。然后我读到了 Image 和 BufferedImage 之间的区别。但我不知道为什么 Image 不能很好地工作,而 BufferedImage 工作得很好。(你能解释一下吗?请)

private HashMap&lt;String, Image&gt; qwirkleImages;

改为

private HashMap&lt;String, BufferedImage&gt; qwirkleImages;

这里是固定代码。这是result image

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class UserPanel extends JPanel implements MouseListener 

    private BIsource draw;
    private BufferedImage bi;

    public UserPanel() 

        this.draw = new BIsource();
        this.bi = draw.getBI();
        this.addMouseListener(this);
    

    @Override
    protected void paintComponent(Graphics g) 
        // TODO Auto-generated method stub
        g.drawImage(bi, 0, 0, this);
    

    @Override
    public void mouseClicked(MouseEvent e) 
        this.draw.drawVrImage();
        this.draw.drawRealImage();
        this.draw.incIndex();
        bi = this.draw.getBI();
        this.repaint();
    

    class BIsource 

        private BufferedImage biCanvas;
//      private HashMap<String, Image> qwirkleImages;
        private HashMap<String, BufferedImage> qwirkleImages;
        private HashMap<String, BufferedImage> imageMap;

        private int index = 0;

        public BIsource() 
            this.qwirkleImages = new HashMap<>();
            this.loadAllImage();

            // biCanvas Declaration
            biCanvas = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics g = biCanvas.createGraphics();
            g.setColor(Color.blue);
            g.fillRect(0, 0, 500, 500);
            g.dispose();

            imageMap = new HashMap<>();
            this.createVrImage();
        

        public void loadAllImage() 
            String key;
            try 
                for (Qwirkle.Color color : Qwirkle.Color.values()) 
                    for (Qwirkle.Shape shape : Qwirkle.Shape.values()) 
                        key = new String(color.toString() + " " + shape.toString());
                        qwirkleImages.put(key, GUI.loadImage2(key + ".jpg"));
                        System.out.println(key);
                    
                
             catch (Exception e) 
                e.printStackTrace();
            
        

        private void createVrImage() 
            BufferedImage vrImage = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB_PRE);
            Graphics g = vrImage.createGraphics();
            g.setColor(Color.red);
            g.fillRect(0, 0, 50, 48);
            g.dispose();

            this.imageMap.put("TEST IMAGE", vrImage);
        

        public BufferedImage getBI() 
            return this.biCanvas;
        

        public void drawVrImage() 
            Graphics g = biCanvas.createGraphics();
            g.drawImage(this.imageMap.get("TEST IMAGE"), 0, index * 50, null);
            g.dispose();
        

        public void drawRealImage() 
            Graphics g = biCanvas.getGraphics();
            Image image = this.qwirkleImages.get("RED STAR");
            if (image == null) 
                System.out.println("image is null");
            
            g.drawImage(image, 200, index * 50, null);
            System.out.println("DRAW Real");
            g.dispose();
        

        public void incIndex() 
            index += 1;
        
    

    public static void main(String[] args) 

        System.out.println("load all images");
        JFrame mainFrame = new JFrame("Test Frame");
        mainFrame.setLayout(null);
        mainFrame.setSize(500, 500);
        mainFrame.setVisible(true);
        mainFrame.setBackground(Color.black);
        mainFrame.setLocation(800, 400);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        UserPanel userPanel = new UserPanel();
        mainFrame.add(userPanel);
        userPanel.setSize(500, 500);
        userPanel.setVisible(true);

    

    @Override
    public void mouseEntered(MouseEvent e) 
    

    @Override
    public void mouseExited(MouseEvent e) 
    

    @Override
    public void mousePressed(MouseEvent e) 
    

    @Override
    public void mouseReleased(MouseEvent e) 
    

【讨论】:

以上是关于某些图像无法立即绘制的主要内容,如果未能解决你的问题,请参考以下文章

在图像视图上绘制矩形。图像无法正确缩放 - iOS

无法在javascript中将图像绘制到画布

无法使用 JComponent 绘制简单图像

使用图像无法正确缩放的绘制视图缩放:Android

绘制太大而无法放入 QImage 的图像

填充某些属性的javascript异步调用