Hi I found a class ReadingPixels someone wrote on the net which given an image it dispays the x,y,r,g,b values as the mouse is over the image. I have a separate class I want to add the panel to. I can add the panel to my frame however I think the problem is that the image is not being passed to the ReadingPixels class.

ReadingPixels

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

public class ReadingPixels extends JPanel {
    BufferedImage image;
    JLabel[] labels;

    public ReadingPixels(BufferedImage image) {
        this.image = image;
        addMouseMotionListener(mml);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int x = (getWidth() - image.getWidth())/2;
        int y = (getHeight() - image.getHeight())/2;
        g.drawImage(image, x, y, this);
    }

    public Dimension getPreferredSize() {
        return new Dimension(image.getWidth(), image.getHeight());
    }

    private void showPixel(Point p) {
        int w = getWidth();
        int h = getHeight();
        int iw = image.getWidth();
        int ih = image.getHeight();
        Rectangle rect = new Rectangle(iw, ih);
        rect.x = (w - iw)/2;
        rect.y = (h - ih)/2;
        int x = 0, y = 0, a = 0, r = 0, g = 0, b = 0;
        if(rect.contains(p)) {
            x = p.x - rect.x;
            y = p.y - rect.y;
            int pixel = image.getRGB(x, y);
            a = (pixel >> 24) & 0xff;
            r = (pixel >> 16) & 0xff;
            g = (pixel >>  8) & 0xff;
            b = (pixel >>  0) & 0xff;
        }
        setLabels(x, y, a, r, g, b);
    }

    private void setLabels(int x, int y, int a, int r, int g, int b) {
        labels[0].setText(String.valueOf(x));
        labels[1].setText(String.valueOf(y));
        labels[2].setText(String.valueOf(a));
        labels[3].setText(String.valueOf(r));
        labels[4].setText(String.valueOf(g));
        labels[5].setText(String.valueOf(b));
    }

    private JPanel getLabels() {
        labels = new JLabel[6];
        for(int i = 0; i < labels.length; i++) {
            labels[i] = new JLabel();
        }
        Dimension d = new Dimension(35, 25);
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(2,2,2,2);
        addComponents("x =", labels[0], panel, gbc, d, 1.0, 0  );
        addComponents("y =", labels[1], panel, gbc, d, 0,   1.0);
        addComponents("a =", labels[2], panel, gbc, d, 1.0, 0  );
        addComponents("r =", labels[3], panel, gbc, d, 0,   0  );
        addComponents("g =", labels[4], panel, gbc, d, 0,   0  );
        addComponents("b =", labels[5], panel, gbc, d, 0,   1.0);
        return panel;
    }

    private void addComponents(String s, JComponent jc, Container c,
                               GridBagConstraints gbc, Dimension d,
                               double weightx1, double weightx2) {
        gbc.weightx = weightx1;
        gbc.anchor = GridBagConstraints.EAST;
        c.add(new JLabel(s), gbc);
        jc.setPreferredSize(d);
        gbc.weightx = weightx2;
        gbc.anchor = GridBagConstraints.WEST;
        c.add(jc, gbc);
    }

    public static void main(String[] args) throws IOException {
        File file = new File("images/blackBear.jpg");
        BufferedImage image = javax.imageio.ImageIO.read(file);
        ReadingPixels test = new ReadingPixels(image);
        JFrame f = new JFrame("ReadingPixels");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new JScrollPane(test));
        f.add(test.getLabels(), "Last");
        f.setSize(500,400);
        f.setLocation(200,200);
        f.setVisible(true);
    }

    private MouseMotionListener mml = new MouseMotionAdapter() {
        public void mouseMoved(MouseEvent e) {
            Point p = e.getPoint();
            showPixel(p);
        }
    };
}

How my class RunProgram works is that the user selects an image to open. So what I want is when the image is open I want the ReadPixels class to display the pixel information of that image that is loaded.

This is the code in my class that opens a picture on a panel

/** Method which takes an image file and opens it on a panel
     * @param f file to be opened
     * @return fileR
     */
    public File openFileR(File f) {
        try {
            tmpImageR = ImageIO.read(f);
            Image toGray = (Image) tmpImageR;
            largeImageR = new ImageIcon(toGray);
            rightPic = new JLabel(largeImageR);
            rightPic.setBorder(new OvalBorder());
        } catch (IOException ex) {
        }
        rightPic.setPreferredSize(new Dimension(350, 350));
        pic2.add(rightPic);
        return fileR;
    }
}

I'm not too sure how to connect this to my class. Can anyone help?
Thank you

Dani AI

Generated

The problem is that the component actually showing the picture is not the same component that has the mouse listener. In the thread added a JLabel (leftPic/rightPic) to display the ImageIcon and also added the ReadingPixels/PicturePanel. Because the JLabel is the visible component (and/or the layout stacked them), mouse events go to the JLabel (or to the labels panel), not to the ReadingPixels panel that does the getRGB work — which explains why pixel values only change when hovering the labels area.

Fixes (choose one):

  • Preferred: make ReadingPixels the view component for the image. Create a ReadingPixels instance with the BufferedImage you loaded, add that instance to the same container where the image belongs, and add its getLabels() panel to the SOUTH (or bottom) of the same container. Remove the separate JLabel for the image (or keep it as a small thumbnail). After changing components call revalidate() and repaint().

Example pattern:

BufferedImage bi = ImageIO.read(file);
ReadingPixels rp = new ReadingPixels(bi);
pic1.removeAll();
pic1.setLayout(new BorderLayout());
pic1.add(rp, BorderLayout.CENTER);
pic1.add(rp.getLabels(), BorderLayout.SOUTH);
pic1.revalidate();
pic1.repaint();
  • Alternative (if you must keep the JLabel): attach a MouseMotionListener to the JLabel, translate mouse coordinates into image coordinates (account for centering and any scaling), then call bufferedImage.getRGB(x,y) yourself and update the label panel. Don’t rely on a listener attached to a different component.

Other practical tips:

  • Use a layout that doesn’t let components overlap (BorderLayout, GridBagLayout). Default FlowLayout can leave components stacked and hidden.
  • If the image is scaled when painted, compute the scale factor so the mouse location maps correctly to the BufferedImage coordinates.
  • Update the UI on the EDT (SwingUtilities.invokeLater) and check for null images before creating ReadingPixels.
  • See ’s note: the ReadingPixels main(...) is a small usage example of how to construct and add the component.

Recommended Answers

All 3 Replies

Look at the main(...) method in the ReadingPixels class. It is an example of how to call/use the class.

I have a class which implements a JPanel and when an image is loaded, it is loaded to that panel. Because this too is a panel I tried merging it will my image panel class however it doesn't work. I wanted a way for the lables to be added to the bottom of my panel. I tried doing this:

public File openFileL(File f) {
        try {
            tmpImageL = ImageIO.read(f);
            tmpImageL = createGrayscalePic(tmpImageL);
//            runGrabPixels(tmpImage);
            Image toGray = (Image) tmpImageL;
            largeImageL = new ImageIcon(toGray);
            leftPic = new JLabel(largeImageL);
            leftPic.setBorder(new OvalBorder());
        } catch (IOException ex) {
        }
        leftPic.setPreferredSize(new Dimension(350, 350));
        pic1.add(leftPic);
        PicturePanel p = new PicturePanel(tmpImageL);
        pic1.add(p);
        return fileL;
    }

I have run the code again and the labels are added to the bottom of my screen but however only the values are shown when i scroll over those lables. It seems that the picture is not on the same panel therefore when I scroll over it nothing happens. How could I rectify this?

Thank you

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.