How to capture colors from an image on a Jlabel that behind another Jlabel?

Asked

Viewed 315 times

1

I need to get the pixel colors of an image inserted in a JLabel with MouseMotionListener, and this Jlabel is under or behind another Jlabel. I know it is possible to get a background color behind a Jlabel, but what I need to capture are colors of an image that are embedded in a Jlabel.

This is the code:

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;


public class Main extends JFrame {

public static void main(String[] args) throws AWTException
{
    JFrame frame;
    Robot robot;
    JLayeredPane layeredPane;
    MouseMotionListener ml;

    robot = new Robot();
    frame = new JFrame("Pc");
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

    layeredPane = new JLayeredPane();
    layeredPane.setPreferredSize(new Dimension(300, 310));
    layeredPane.setBorder(BorderFactory.createTitledBorder(
                                "capture color under the label"));
    JLabel label = new JLabel(new ImageIcon("folder/matiz.jpg"));
    label.setBounds(15, 15, 300, 300);
    label.setOpaque(true);
    label.setBackground(Color.red);

    JLabel label1 = new JLabel();
    label1.setBounds(60, 60, 300, 300);
    label1.setOpaque(true);
    label1.setBackground(new Color(255,255,255));

    layeredPane.add(label, 0, 0);
    layeredPane.add(label1, 1, 0);


    frame.setSize(660, 400);

    frame.getContentPane().setBackground(Color.red);
    frame.setGlassPane(layeredPane);
    layeredPane.setVisible(true);
    frame.setVisible(true); 

       ml = new MouseMotionAdapter() {

      public void mouseMoved(MouseEvent evt) {

          JLabel comp = (JLabel) evt.getSource();
          Point point = evt.getLocationOnScreen();

                Color color = robot.getPixelColor((int)point.getX(),(int)point.getY());
                System.out.println(color);
            }
  };        
            label1.removeMouseMotionListener(ml);
            label.addMouseMotionListener(ml);
    }
}
  • Is this code the same as the other question? There’s an unnecessary line there that I told you in the answer and you kept.

  • When you hover over the top label it captures the white color and what I need the mouse to read only the RGB of the label that is below even passing the mouse over the white. The mouse event must disregard the upper label.

1 answer

3


First of all I want to leave two alerts on your code:

Always start the screen inside the Event-Dispatch-Thread, because swing is not Thread-Safe, and the entire GUI needs to start within this single Thread. In this answer better explains the reason for this and any problems that may occur. This other answer shows some ways to start the application within this thread.

Avoid using absolute layout, the swing API provides several Layouts Managers to facilitate the life of the programmer when creating screens, besides making the screen flexible to different sizes of monitors and resolutions , without it being necessary to treat this directly in the code. Absolute layout will break the appearance of your application depending on the monitor where the application runs.


Using the class BufferedImage, you can recover the RGB colors of an image. First, you must create an instance of that class by passing the image dimensions:

BufferedImage bufImage = new BufferedImage(image.getIconWidth(), image.getIconHeight(),
                BufferedImage.TYPE_INT_RGB);

After that, you need to "fill" the buffer with the image. Jlabel is filled by a ImageIcon but the method drawimage() wait for a guy Image. This type can be recovered from Imageicon by the method getimage():

    ImageIcon imgIcon= label.getIcon();
    Graphics g = bufImage.createGraphics();
    
    g.drawImage(imgIcon.getImage(), 0, 0, null);

With the image already "buffered", just use the method getRGB(x,y) to recover the RGB value of the pixel, according to the coordinates passed by the mouse movement, limiting to the size of the image:

    int x = (int) e.getX();
    int y = (int) e.getY();

    if(x < imgIcon.getIconWidth() && y < imgIcon.getIconHeight()){
        int rgb = bufImage.getRGB(x, y);
        System.out.println(new Color(rgb));
    }

Just by inserting these snippets into your method mouseMoved would already solve the problem, but to separate the responsibility of handling the label from the main class, better organize the code and make the component reusable, you can create a class of JLabel custom and apply these changes only to it. In this case, I created the class CustomLabel to exemplify:

class CustomLabel extends JLabel implements MouseMotionListener {

    private ImageIcon image;

    public CustomLabel(ImageIcon image) {
        this.image = image;
        setIcon(image);
        this.addMouseMotionListener(this);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // TODO Auto-generated method stub
    }

    @Override
    public void mouseMoved(MouseEvent e) {

        int x = (int) e.getX();
        int y = (int) e.getY();

        BufferedImage bufImage = new BufferedImage(image.getIconWidth(), image.getIconHeight(),
                BufferedImage.TYPE_INT_RGB);
        
        Graphics g = bufImage.createGraphics();
        
        g.drawImage(image.getImage(), 0, 0, null);

        if(x < image.getIconWidth() && y < image.getIconHeight()){
            int rgb = bufImage.getRGB(x, y);
            System.out.println(new Color(rgb));
        }

    }
}

To use in your code, simply create this class in your project and replace:

JLabel label = new JLabel(new ImageIcon("folder/matiz.jpg"));

for:

CustomLabel label = new CustomLabel(new ImageIcon("folder/matiz.jpg"));

See a functional example of your code with the above class:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.net.*;

public class GetPixelImageComponent {

    public void showAndCreateGUI() throws MalformedURLException, AWTException {

        JFrame frame;
        Robot robot;
        JLayeredPane layeredPane;
        MouseMotionListener ml;

        robot = new Robot();
        frame = new JFrame("Pc");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        layeredPane = new JLayeredPane();
        layeredPane.setPreferredSize(new Dimension(300, 310));
        layeredPane.setBorder(BorderFactory.createTitledBorder("capture color under the label"));
        


        /** ESTAS DUAS LINHAS SÃO APENAS PARA DEMONSTRAÇÃO **/
        URL url = new URL("http://wimages.vr-zone.net/2013/06/10-15-2012-2-22-52-PM-300x300.png");
        CustomLabel label = new CustomLabel(new ImageIcon(url));
        
        //CustomLabel label = new JLabel(new ImageIcon("folder/matiz.jpg"));        
        label.setBounds(15, 15, 300, 300);
        label.setOpaque(true);
        label.setBackground(Color.black);

        JLabel label1 = new JLabel();
        label1.setBounds(60, 60, 300, 300);
        label1.setOpaque(true);
        label1.setBackground(new Color(255, 255, 255));

        layeredPane.add(label, 0, 0);
        layeredPane.add(label1, 1, 0);

        frame.setSize(660, 400);

        frame.getContentPane().setBackground(Color.red);
        frame.setGlassPane(layeredPane);
        layeredPane.setVisible(true);
        frame.setVisible(true);

    }

    public static void main(String[] args) throws Exception {
        EventQueue.invokeLater(() -> {
            try {
                new GetPixelImageComponent().showAndCreateGUI();
            } catch (MalformedURLException | AWTException e) {
                e.printStackTrace();
            }
        });
    }

    class CustomLabel extends JLabel implements MouseMotionListener {

        private ImageIcon image;

        public CustomLabel(ImageIcon image) {
            this.image = image;
            setIcon(image);
            this.addMouseMotionListener(this);
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            // TODO Auto-generated method stub
        }

        @Override
        public void mouseMoved(MouseEvent e) {

            int x = (int) e.getX();
            int y = (int) e.getY();

            BufferedImage bufImage = new BufferedImage(image.getIconWidth(), image.getIconHeight(),
                    BufferedImage.TYPE_INT_RGB);
            
            Graphics g = bufImage.createGraphics();
            
            g.drawImage(image.getImage(), 0, 0, null);

            if(x < image.getIconWidth() && y < image.getIconHeight()){
                int rgb = bufImage.getRGB(x, y);
                System.out.println(new Color(rgb));
            }

        }
    }
}

Which results in:

inserir a descrição da imagem aqui

  • 1

    As always your help and answers are fantastic. Thanks again Diego! :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.