如何逐个绘制图像? [英] How can I draw an image part by part?

查看:108
本文介绍了如何逐个绘制图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class DrawIma extends JPanel{
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        for (int i=0;i<20;i++){
            for (int j=0;j<20;j++) {    
                g.drawImage(BuArr[i*20+j], 20*i, 20*j, 20, 20, null);
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这部分中, BuArr 是从 BufferedImage 划分的 400块,现在我希望它们逐个绘制,但该方法不能单独绘制块,我该怎么做?

In this part, BuArr are the 400 blocks divided from a BufferedImage, now i want them to be draw one by one, but the method can not draw the blocks separately, how can i do this?

推荐答案

Swing是单线程而不是线程安全的。

Swing is single thread and not thread safe.

这意味着你不应该在IU线程中执行任何长时间运行或阻塞( Thread.sleep )操作(事件调度线程)。这也意味着您无法在EDT上下文之外更新,修改或创建UI元素。

This means that you should not perform any long running or blocking (Thread.sleep) operations within the IU thread (the Event Dispatching Thread). It also means that you can not update, modify or create UI elements outside of the EDT context.

相反,使用Swing 计时器以指定的间隔生成重复的回调,并将图像的部分渲染为类似 BufferedImage 的部分,您可以通过其 paintComponent method ...

Instead, use a Swing Timer to generate a repeated callback at a specified interval and render the portions of the image to something like a BufferedImage, which you can the paint to the component via its paintComponent method...

参见 Swing中的并发如何使用Swing Timers 获取更多详细信息

See Concurrency in Swing and How to use Swing Timers for more details

因为这是浪费时间

这会生成一个 List Rectangles ,它代表各个块I我想绘画,然后随机化列表并运行计时器,选择最顶层的矩形关闭列出并使用 BufferedImage#getSubImage 将其从主控制器绘制到缓冲区,并将其绘制到屏幕上。 。

This generates a List of Rectangles which represent the individual blocks I want to paint, I then randomise the List and run the Timer, picking the top most Rectangle off the List and using BufferedImage#getSubImage to draw it from the master to the buffer, which gets painted to the screen...

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestImage {

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

    public TestImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage master;
        private BufferedImage copy;

        private List<Rectangle> blocks;

        public TestPane() {
            setBackground(Color.BLACK);
            try {
                master = ImageIO.read(new File("..."));
                copy = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = copy.createGraphics();
                AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
                g2d.setComposite(composite);
                g2d.setColor(new Color(0, 0, 0, 0));
                g2d.fillRect(0, 0, master.getWidth(), master.getHeight());
                g2d.dispose();

                int blockSize = 40;

                int width = master.getWidth();
                int height = master.getHeight();

                float aspect = Math.min(width, height) / (float) Math.max(width, height);

                int blockHeight = blockSize;
                blocks = new ArrayList<>(blockSize * 2);
                for (int y = 0; y < master.getHeight(); y += blockHeight) {
                    if (y + blockHeight > master.getHeight()) {
                        blockHeight = master.getHeight() - y;
                    }
                    int blockWidth = blockSize;
                    for (int x = 0; x < master.getWidth(); x += blockWidth) {
                        if (x + blockWidth > master.getWidth()) {
                            blockWidth = master.getWidth() - x;
                        }
                        Rectangle block = new Rectangle(x, y, blockWidth, blockHeight);
                        blocks.add(block);
                    }
                }
                Collections.shuffle(blocks);
                Timer timer = new Timer(40, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        if (blocks.isEmpty()) {
                            ((Timer) e.getSource()).stop();
                        } else {
                            Graphics2D g2d = copy.createGraphics();
                            Rectangle block = blocks.remove(0);
                            g2d.drawImage(master.getSubimage(block.x, block.y, block.width, block.height), block.x, block.y, TestPane.this);
                            g2d.dispose();
                            repaint();
                        }
                    }
                });

                timer.start();

            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return master == null ? new Dimension(200, 200) : new Dimension(master.getWidth(), master.getHeight());
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (copy != null) {
                int x = (getWidth() - copy.getWidth()) / 2;
                int y = (getHeight() - copy.getHeight()) / 2;
                g2d.drawImage(copy, x, y, this);
            }
            g2d.dispose();
        }

    }

}

这篇关于如何逐个绘制图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆