1

I discovered the Robot class yesterday, and thought it was pretty cool. Today I wanted to experiment with it and see what was possible; so I decided I wanted to make a program that took a screenshot of the entire screen, and rendered out an image pixel by pixel on a JPanel. I have the program finished (two classes), but it isn't working and I can't find out why (I HAVE looked over the code a few times). Here's the code:

(FIRST CLASS)

import java.awt.AWTException;
import java.awt.FlowLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;

public class One { 
    public static void main(String[] args) { 
        BufferedImage screenCap = null;
        Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
        try {
            screenCap = new Robot().createScreenCapture(screenRect);
            Two imageRenderer = new Two(screenCap, screenRect);
            imageRenderer.doRender();
            JFrame frame = new JFrame();
            frame.setVisible(true);
            frame.setResizable(false);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new FlowLayout());
            frame.add(imageRenderer);
            frame.pack();
        } catch (AWTException e) { 
            e.printStackTrace(); 
        } 
    } 
}

(SECOND CLASS)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

public class Two extends JPanel {
    private BufferedImage screenCap;
    private Rectangle screenRect;

    private Color pixelRGB;
    //c1 and c2 are the x and y co-ordinates of the selected pixel.
    private int c1, c2;

    public Two(BufferedImage sC, Rectangle rect) {
        screenCap = sC;
        screenRect = rect;
        setPreferredSize(new Dimension(rect.width, rect.height));
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        setBackground(Color.WHITE);

        g.setColor(pixelRGB);
        g.drawRect(c1, c2, 1, 1);
    }

    public void doRender() {
        for(int i=0; i<screenRect.width; i++) {
            for(int j=0; j<screenRect.height; j++) {
                pixelRGB = new Color(screenCap.getRGB(i, j));
                c1 = i;
                c2 = j;
                repaint();
            }
        }
    }
}

I have googled around this problem to no avail.

Can anyone tell me what I'm doing wrong?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Ronan H
  • 151
  • 1
  • 1
  • 6

3 Answers3

3

In order to make it work, just replace your paintComponent() method in your class Two with the following:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    setBackground(Color.WHITE);
    g.drawImage(screenCap, 0, 0, getWidth(), getHeight(), null);
}

You can also get rid of the doRender() method.

Dan D.
  • 32,246
  • 5
  • 63
  • 79
1

Two should probably be an instance of a JLabel that is displaying screenCap. E.G.

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

public class Screenshot {

    public static void main(String[] args) throws Exception {
        Rectangle screenRect = new Rectangle(
                Toolkit.getDefaultToolkit().getScreenSize());

        final BufferedImage screenCap = 
                new Robot().createScreenCapture(screenRect);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                JOptionPane.showMessageDialog(null, new ImageIcon(screenCap));
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

Drop it in a scroll pane if you wish to be really neat about it. Batteries not included.

In case it is not obvious: A JOptionPane uses a JLabel to render an ImageIcon.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
0

Each time you repaint, you paint white over the whole panel, then do only a single pixel. So after each one, you'll only get one pixel. It also shouldn't be necessary to call repaint many times. In fact, when you call repaint, it does not immediately actually call paintComponent. It simply submits a request to repaint, which swing will eventually do. And it might not be one-to-one. E.g., many calls to repaint might result in only one call to paintComponent. You should try to write code so that a single call to paintComponent will completely display the component.

To do this, you can use g.drawImage to display a BufferedImage. See this post for more information on displaying an image in a JPanel.

Community
  • 1
  • 1
Joe K
  • 18,204
  • 2
  • 36
  • 58