JAVA: JFrame 变黑后的截图

JAVA: Screenshot after JFrame change just black

我编写了一个程序,通过单击 JMenuItem 来制作 JFrame 的屏幕截图。如果我在 Eclipse 中只 运行 .java 文件,一切正常,屏幕截图完美显示 JFrame。但是如果我从另一个 JFrame 打开 JFrame 作为 link,屏幕截图是黑色的而不是显示 JFrame。这是我的代码:

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);
                }
        });    
    }
}

用一个按钮(ok)我可以去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();
    }

}

如果我现在点击 "Screenshot",它就是黑色的。 而如果我之前运行只JFrame2.java而没有运行宁JFrame1.java,则保存真实图像。 为什么从一个JFrame1转到JFrame2后截图是黑色的?

你画错了框架...

在您的第一帧中,您正在这样做...

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

看起来很无害,但是,在 JFrame2 你正在这样做......

public class JFrame2 extends JFrame {

    static JFrame2 frame2 = new JFrame2();

还有...

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 ();
    }
}

但是,frame2(在 JFrame2 内)在屏幕上不可见。

这就是为什么 static 是邪恶的,应该避免。这也是为什么你不应该直接从 JFrame 这样的东西扩展的原因。您很容易陷入不知道屏幕上实际显示的内容以及您所引用的内容的困境...

例如...

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());
                }

            }
        }

    }

}

这将输出...