How can I draw an image part by part?

*爱你&永不变心* 提交于 2019-12-02 15:08:52

问题


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();
                }
            }
        }
    }
}

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?


回答1:


Swing is single thread and not thread safe.

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.

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...

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

Because it was a good time waster

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();
        }

    }

}


来源:https://stackoverflow.com/questions/27163399/how-can-i-draw-an-image-part-by-part

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!