Split image into clickable regions

前端 未结 2 1677
予麋鹿
予麋鹿 2020-12-18 08:41

Is there any way to split an image to region (right now it\'s JLabel but I can change it if necessary)?
I use swing in my program and I have an image (square for this ex

相关标签:
2条回答
  • 2020-12-18 08:45

    You can use the getSubImage() method of BufferedImage, illustrated here and here. The example also uses JLabel, but you can add the Icon to a JButton that can be clicked. There are several ways for a button to remember details about it's icon:

    • Subclass JButton and add a suitable field.
    • Add a client property to the parent JComponent.
    • Use the name property of the parent Component.
    0 讨论(0)
  • 2020-12-18 09:03

    Have a look at what I have made:

    This is the image I used for testing:

    Original Image

    After image has been split:

    After Image splitting

    And here is the source:

    import java.awt.Graphics2D;
    import java.awt.GridLayout;
    import java.awt.Toolkit;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    
    public class Test {
    
        private JFrame frame;
        private JLabel[] labels;
        private static String imagePath = "c:/test.jpg";
        private final int rows = 3; //You should decide the values for rows and cols variables
        private final int cols = 3;
        private final int chunks = rows * cols;
        private final int SPACING = 10;//spacing between split images
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new Test().createAndShowUI();
                }
            });
        }
    
        private void createAndShowUI() {
            frame = new JFrame("Test");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            initComponents();
            frame.setResizable(false);
            frame.pack();
            frame.setVisible(true);
        }
    
        private void initComponents() {
    
            BufferedImage[] imgs = getImages();
    
            //set contentpane layout for grid
            frame.getContentPane().setLayout(new GridLayout(rows, cols, SPACING, SPACING));
    
            labels = new JLabel[imgs.length];
    
            //create JLabels with split images and add to frame contentPane
            for (int i = 0; i < imgs.length; i++) {
                labels[i] = new JLabel(new ImageIcon(Toolkit.getDefaultToolkit().createImage(imgs[i].getSource())));
                frame.getContentPane().add(labels[i]);
            }
        }
    
        private BufferedImage[] getImages() {
            File file = new File(imagePath); // I have bear.jpg in my working directory
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
            } catch (FileNotFoundException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            }
            BufferedImage image = null;
            try {
                image = ImageIO.read(fis); //reading the image file
            } catch (IOException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            }
            int chunkWidth = image.getWidth() / cols; // determines the chunk width and height
            int chunkHeight = image.getHeight() / rows;
            int count = 0;
            BufferedImage imgs[] = new BufferedImage[chunks]; //Image array to hold image chunks
            for (int x = 0; x < rows; x++) {
                for (int y = 0; y < cols; y++) {
                    //Initialize the image array with image chunks
                    imgs[count] = new BufferedImage(chunkWidth, chunkHeight, image.getType());
    
                    // draws the image chunk
                    Graphics2D gr = imgs[count++].createGraphics();
                    gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null);
                    gr.dispose();
                }
            }
            return imgs;
        }
    }
    

    The only flaw is I haven't checked if the image is larger then the screen which could cause problems, that would be resolved by a simple image resize using getScaledInstance(int x,int y, int width, in height) on the image and the separating it into chunks.

    Update

    Sorry I missed the part if the question in Shapes, have a look at draw(Shape s) method of Graphics2D/Graphics.

    I read this:

    Any Shape object can be used as a clipping path that restricts the portion of the drawing area that will be rendered. The clipping path is part of the Graphics2D context; to set the clip attribute, you call Graphics2D.setClip and pass in the Shape that defines the clipping path you want to use.

    See here for clipping an u]image to a shape: Clipping the Drawing Region

    References:

    • How to Split an Image into Chunks - Java ImageIO
    0 讨论(0)
提交回复
热议问题