【问题标题】:Print the whole program layout打印整个程序布局
【发布时间】:2013-05-24 14:41:29
【问题描述】:

我使用 Netbeans 制作了一个 Java 程序(基于JFrame), 我想知道是否可以打印程序的布局

我希望有一个按钮并将功能设置为“打印” 并且将打印框架的最终布局,这可能吗? 如果有,有参考来源吗?

【问题讨论】:

  • 我的意思是它使用打印到打印机,而不是 printscreen

标签: java swing printing jframe awt


【解决方案1】:

这取决于您希望达到的目标。

您可以简单地将框架的内容打印到BufferedImage。这使您可以控制要捕获的内容,因为您可以打印内容窗格而不是框架。

您可以使用Robot 来捕获屏幕。这将在您尝试捕获的位置捕获屏幕上的任何内容,其中可能包括更多内容,而不仅仅是您的框架......

“打印”与“捕获”

import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class PrintFrame {

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

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

                JLabel label = new JLabel("Clap if you're happy");

                final JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(label);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);

                InputMap im = label.getInputMap(JLabel.WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = label.getActionMap();

                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK), "Print");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK), "PrintAll");

                am.put("Print", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        try {
                            System.out.println("Print...");
                            BufferedImage img = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
                            Graphics2D g2d = img.createGraphics();
                            frame.printAll(g2d);
                            g2d.dispose();
                            ImageIO.write(img, "png", new File("Print.png"));
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                });
                am.put("PrintAll", new AbstractAction() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        try {
                            System.out.println("PrintAll...");
                            Robot bot = new Robot();
                            Rectangle bounds = frame.getBounds();
                            bounds.x -= 2;
                            bounds.y -= 2;
                            bounds.width += 4;
                            bounds.height += 4;
                            BufferedImage img = bot.createScreenCapture(bounds);
                            ImageIO.write(img, "png", new File("PrintAll.png"));
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                });

                frame.setVisible(true);

            }
        });
    }
}

更新了更好的要求

基本要求没有太大变化。您仍然需要以某种方式捕获屏幕...

这里我修改了“打印”代码,将生成的BufferedImage 发送到打印机。请注意,我没有检查图像是否真的适合,我相信你可以解决这个问题;)

am.put("Print", new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            System.out.println("Print...");
            BufferedImage img = new BufferedImage(frame.getWidth(), frame.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = img.createGraphics();
            frame.printAll(g2d);
            g2d.dispose();
            PrinterJob pj = PrinterJob.getPrinterJob();
            pj.setPrintable(new FramePrintable(img));
            if (pj.printDialog()) {
                pj.print();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
});

然后,您只需要某种方式将内容实际渲染到打印机...

public class FramePrintable implements Printable {

    private BufferedImage img;

    public FramePrintable(BufferedImage img) {
        this.img = img;
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {

        if (pageIndex == 0) {

            Graphics2D g2d = (Graphics2D) graphics;
            g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
            double x = (pageFormat.getImageableWidth() - img.getWidth()) / 2;
            double y = (pageFormat.getImageableHeight()- img.getHeight()) / 2;
            g2d.drawImage(img, (int)x, (int)y, null);

        }

        return pageIndex == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
    }
}

这几乎是直接取自 Printing 试用版...

【讨论】:

  • 我的意思是它使用打印到打印机,而不是 printscreen
  • 好的,现在你有一个BufferedImage,你可以用Printable来打印它,见Printing一些想法;)
  • 更新了“打印”示例
【解决方案2】:

最简单的方法是使用Robot 类,它可以在给定坐标处捕获屏幕片段。看看这个讨论:Java print screen program

只需将 JFrame 的绝对坐标发送给机器人

【讨论】:

  • 我的意思是它使用打印到打印机,而不是 printscreen
【解决方案3】:

尝试截取屏幕截图并将其保存到文件中。然后就可以打印文件了。下面的代码sn -p可以用来截图:

boolean captureScreenShot()
{
      boolean isSuccesful = false;
      Rectangle screenRect = new Rectangle(0,0,500,500);//frame absolute coordinates
      BufferedImage capture;
      try {
          capture = new Robot().createScreenCapture(screenRect);
          // screen shot image will be save at given path with name "screen.jpeg"
          ImageIO.write(capture, "jpg", new File( "c:\\abc", "screen.jpeg"));
          isSuccesful = true;
      } catch (AWTException awte) {
          awte.printStackTrace();
          isSuccesful = false;
      }
      catch (IOException ioe) {
          ioe.printStackTrace();
          isSuccesful = false;
      }
      return isSuccesful;
}

【讨论】:

  • 我的意思是它使用打印到打印机,而不是 printscreen
  • "screen.png" 包含您要打印的框架。您现在可以将此文件(“screen.png”)打印到打印机。谷歌一下。
  • 然后改变框架的坐标,排除窗框;如将坐标设为 (0,10,500,500)。
  • 就像在设置矩形的坐标时只包含你的框架的内容!
  • @Rishabh 随意更改矩形不是一个好主意。并非所有系统都是平等的。如果您运行的是不同的操作系统,甚至是具有不同字体设置的同一个操作系统,会发生什么
猜你喜欢
  • 2016-11-06
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2011-07-31
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多