1

I've written a program which makes a screenshot of JFrame by clicking on JMenuItem. If I only run the .java file in Eclipse, everything works and the screenshot shows the JFrame perfectly. But if I open the JFrame as a link from another JFrame, the screenshot is black instead of showing the JFrame. Here's my code:

JFrame1.java:

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;


public class JFrame1 extends JFrame {

    static JFrame1 frame1 = new JFrame1();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
             try {
                 frame1.setVisible(true);

            } catch (Exception e) {
              e.printStackTrace();
            }

          }
        });   
      }

    public void CloseFrame(){
        super.dispose();
    }    

    public JFrame1() {
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(50, 50, 800, 740);

        JButton ok = new JButton("OK");
        getContentPane().add(ok);
        ok.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                CloseFrame();
                JFrame2 frame2 = new JFrame2();
                frame2.setVisible(true);
                }
        });    
    }
}

With a button (ok) I can go to JFrame2.java.

JFrame2.java:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class JFrame2 extends JFrame {

    static JFrame2 frame2 = new JFrame2();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
             try {
                 frame2.setVisible(true);

            } catch (Exception e) {
              e.printStackTrace();
            }

          }
        });   
      }

    private void createMenuBar() {

          JMenuBar menubar = new JMenuBar();

          JMenu file = new JMenu("File");

          JMenuItem screen = new JMenuItem("Screenshot");
              screen.addActionListener(new AbstractAction() {

                  @Override
                  public void actionPerformed (ActionEvent e)
                  {
                      Dimension size = frame2.getSize ();
                      BufferedImage img = new BufferedImage (size.width, size.height, BufferedImage.TYPE_3BYTE_BGR);
                      Graphics g = img.getGraphics ();
                      frame2.printAll (g);
                      g.dispose ();
                      try
                      {
                          ImageIO.write (img, "png", new File ("screenshot.png"));
                      }
                      catch (IOException ex)
                      {
                          ex.printStackTrace ();
                      }
                  }
              });

          file.add(screen);
          menubar.add(file);
          setJMenuBar(menubar);
      }

    public JFrame2() {
          setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(50, 50, 800, 740);

        createMenuBar();
    }

}

If I click now on "Screenshot", it is just black. And if I run only JFrame2.java without running JFrame1.java before, the real image is saved. Why does the screenshot is black after going from one JFrame1 to JFrame2?

simon9714
  • 13
  • 3
  • 1
    For better help, consider creating and posting a [Minimal, Complete, and Verifiable Example Program](http://stackoverflow.com/help/mcve). We don't want to see your whole program, but rather you should condense your code into the smallest bit that still compiles, has no extra code that's not relevant to your problem, but still demonstrates your problem. – Hovercraft Full Of Eels Mar 13 '15 at 23:27
  • Also, what if you call `frame2.printAll(g);` instead? Also, your design is somewhat curious if your displaying more than one JFrame at a time as per [this question](http://stackoverflow.com/questions/9554636/the-use-of-multiple-jframes-good-bad-practice). – Hovercraft Full Of Eels Mar 13 '15 at 23:31
  • OK, then step 2: consider creating and posting your [Minimal, Complete, and Verifiable Example Program](http://stackoverflow.com/help/mcve) for us. – Hovercraft Full Of Eels Mar 13 '15 at 23:35
  • I've changed the question for a better understanding. – simon9714 Mar 14 '15 at 00:14
  • And one-plus up-vote for the changes. As usual, when you provide more information, you'll get better answers, as evidenced by MadProgrammer's answer. Good luck with your project! – Hovercraft Full Of Eels Mar 14 '15 at 03:19

1 Answers1

1

You're painting from the wrong frame...

In your first frame, you are doing this...

JFrame2 frame2 = new JFrame2();
frame2.setVisible(true);

Looks pretty harmless, but, in JFrame2 you are doing this...

public class JFrame2 extends JFrame {

    static JFrame2 frame2 = new JFrame2();

And...

public void actionPerformed (ActionEvent e)
{
    Dimension size = frame2.getSize ();
    BufferedImage img = new BufferedImage (size.width, size.height, BufferedImage.TYPE_3BYTE_BGR);
    Graphics g = img.getGraphics ();
    frame2.printAll (g);
    g.dispose ();
    try
    {
        ImageIO.write (img, "png", new File ("screenshot.png"));
    }
    catch (IOException ex)
    {
        ex.printStackTrace ();
    }
}

But, frame2 (inside JFrame2) is not visible on the screen.

This is why static is evil and should be avoid. This is also why you should not extend directly from something like JFrame. You can to easily get yourself into a knot of not knowing what is actually on the screen and what you are referencing...

For example...

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class JavaApplication254 {

    public static void main(String[] args) {
        new JavaApplication254();
    }

    public JavaApplication254() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JButton btn = new JButton("Click me away...");
                btn.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {

                        TestPane testPane = new TestPane();
                        SnapshotAction snapshotAction = new SnapshotAction(testPane);

                        JMenuBar mb = new JMenuBar();
                        JMenu mnuFile = new JMenu("File");
                        mnuFile.add(snapshotAction);
                        mb.add(mnuFile);

                        JFrame frame = new JFrame("More Testing");
                        frame.setJMenuBar(mb);
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        frame.add(testPane);
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    }
                });

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(btn);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setBorder(new EmptyBorder(20, 20, 20, 20));
            JLabel label = new JLabel("I be a bananan");
            label.setOpaque(true);
            label.setBackground(Color.YELLOW);
            label.setForeground(Color.RED);
            label.setBorder(
                    new CompoundBorder(
                            new LineBorder(Color.RED),
                            new EmptyBorder(20, 20, 20, 20)));
            setLayout(new GridBagLayout());
            add(label);
        }

    }

    public class SnapshotAction extends AbstractAction {

        private JComponent parent;

        public SnapshotAction(JComponent parent) {
            this.parent = parent;
            putValue(NAME, "Take Snapshot...");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (parent.isDisplayable()) {

                BufferedImage img = new BufferedImage(parent.getWidth(), parent.getHeight(), BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = img.createGraphics();
                parent.printAll(g2d);
                g2d.dispose();

                try {
                    ImageIO.write(img, "png", new File("Snapshot.png"));
                    Toolkit.getDefaultToolkit().beep();
                } catch (IOException ex) {
                    ex.printStackTrace();
                    JOptionPane.showMessageDialog(parent, "Failed to generate snapshot: " + ex.getMessage());
                }

            }
        }

    }

}

Which will output...

enter image description here

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366