Coordinates of a JTextPane to make a Screenshot in Java

386 views Asked by At

I hope some one can help me, this is what I want to do.

I have a JTextPane and I want to take a screenshot to that specific JTextPane coordinates and size, so far I can do a screenshot with the size of the JTextPane but I can't get the specific coordinates my screenshots always gets the (0,0) coordinates.

This is my method:

void capturaPantalla () 
{
    try
    {
        int x = txtCodigo.getX();
        int y = txtCodigo.getY();

        Rectangle areaCaptura = new Rectangle(x, y, txtCodigo.getWidth(), txtCodigo.getHeight());

        BufferedImage capturaPantalla = new Robot().createScreenCapture(areaCaptura);

        File ruta = new File("P:\\captura.png");

        ImageIO.write(capturaPantalla, "png", ruta);

        JOptionPane.showMessageDialog(null, "Codigo de barras guardado!");      
    }

    catch (IOException ioe) 
    {
        System.out.println(ioe);
    }     

    catch(AWTException ex)
    {
        System.out.println(ex);
    }
} 
2

There are 2 answers

10
Hovercraft Full Of Eels On BEST ANSWER

When you call getX() and getY() on any Swing component, you get the x and y relative to the component's container, not the screen. Instead you want the location of the component relative to the screen and get position based on that via getLocationOnScreen()

Point p = txtCodigo.getLocationOnScreen();
int x = p.x;
int y = p.y;

As per MadProgrammer's comment, you could simply call printAll(Graphics g) on your txtCodigo component, passing in a Graphics object obtained from a properly sized BufferedImage and forgo use of a Robot.

Dimension d = txtCodigo.getSize();
BufferedImage img = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
txtCodigo.printAll(g);
g.dispose();
// use ImageIO to write BufferedImage to file

To compare to the two methods:

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class RobotVsPrintAll extends JPanel {
   private static final int WORDS = 400;
   private JTextArea textArea = new JTextArea(20, 40);
   private JScrollPane scrollPane = new JScrollPane(textArea);
   private Random random = new Random();

   public RobotVsPrintAll() {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < WORDS; i++) {
         int wordLength = random.nextInt(4) + 4;
         for (int j = 0; j < wordLength; j++) {
            char myChar = (char) (random.nextInt('z' - 'a' + 1) + 'a');
            sb.append(myChar);
         }
         sb.append(" ");
      }
      textArea.setText(sb.toString());

      textArea.setLineWrap(true);
      textArea.setWrapStyleWord(true);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

      JButton robot1Btn = new JButton(new Robot1Action("Robot 1"));
      JButton robot2Btn = new JButton(new Robot2Action("Robot 2"));
      JButton printAllBtn = new JButton(new PrintAllAction("Print All"));

      JPanel btnPanel = new JPanel();
      btnPanel.add(robot1Btn);
      btnPanel.add(robot2Btn);
      btnPanel.add(printAllBtn);

      setLayout(new BorderLayout());
      add(scrollPane, BorderLayout.CENTER);
      add(btnPanel, BorderLayout.PAGE_END);
   }

   private void displayImg(BufferedImage img) {
      ImageIcon icon = new ImageIcon(img);
      JOptionPane.showMessageDialog(this, icon, "Display Image", 
            JOptionPane.PLAIN_MESSAGE);
   }

   private class Robot1Action extends AbstractAction {
      public Robot1Action(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         try {
            Component comp = scrollPane.getViewport();
            Point p = comp.getLocationOnScreen();
            Dimension d = comp.getSize();

            Robot robot = new Robot();

            Rectangle screenRect = new Rectangle(p.x, p.y, d.width, d.height);
            BufferedImage img = robot.createScreenCapture(screenRect);
            displayImg(img);

         } catch (AWTException e1) {
            e1.printStackTrace();
         }

      }

   }

   private class Robot2Action extends AbstractAction {
      public Robot2Action(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         try {
            Component comp = textArea;
            Point p = comp.getLocationOnScreen();
            Dimension d = comp.getSize();

            Robot robot = new Robot();

            Rectangle screenRect = new Rectangle(p.x, p.y, d.width, d.height);
            BufferedImage img = robot.createScreenCapture(screenRect);
            displayImg(img);

         } catch (AWTException e1) {
            e1.printStackTrace();
         }

      }

   }

   private class PrintAllAction extends AbstractAction {
      public PrintAllAction(String name) {
         super(name);
         int mnemonic = (int) name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      public void actionPerformed(ActionEvent e) {
         Dimension d = textArea.getSize();
         BufferedImage img = new BufferedImage(d.width, d.height, BufferedImage.TYPE_INT_ARGB);
         Graphics g = img.getGraphics();
         textArea.printAll(g);
         g.dispose();
         displayImg(img);
      }
   }

   private static void createAndShowGui() {
      RobotVsPrintAll mainPanel = new RobotVsPrintAll();

      JFrame frame = new JFrame("Robot Vs PrintAll");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

If you print the text component with printAll, you get the entire text component, even the parts that are not displayed in the JScrollPane's viewport.

1
camickr On

You can use the Screen Image class which does all the work for you. All you do is specify the component you want to capture.

The code would be:

BufferedImage bi = ScreenImage.createImage( component );

And you can save the image to a file using:

ScreenImage.writeImage(bi, "imageName.jpg");

This class will use the painting method of the Swing component which is more efficient than using a Robot.