使用 setVisible(false) 打印 JFrame [英] Print JFrame with setVisible(false)

查看:42
本文介绍了使用 setVisible(false) 打印 JFrame的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个带有 2 个 JFrame 窗口的 Swing 应用程序,我想将第一帧作为主页.我将第一帧中的打印按钮设置为打印第二帧.

如何使用 frame.setVisible(false); 打印第二帧?我该如何解决?

我把我的代码放在下面:

package printuiwindow;/**** @author Saravanan Ponnusamy*/导入 java.awt.*;导入 java.awt.event.*;导入 javax.swing.*;导入 java.awt.print.*;类 PrintUIWindow 实现可打印,ActionListener {JFrame frameToPrint;公共 int print(Graphics g, PageFormat pf, int page) 抛出打印机异常 {如果(页面 > 0){返回 NO_SUCH_PAGE;}Graphics2D g2d = (Graphics2D)g;g2d.translate(pf.getImageableX(), pf.getImageableY()-55);frameToPrint.print(g);返回 PAGE_EXISTS;}公共无效actionPerformed(ActionEvent e){PrinterJob 作业 = PrinterJob.getPrinterJob();job.setPrintable(this);boolean ok = job.printDialog();如果(好){尝试 {作业.print();} 捕捉(打印机异常前){System.out.println(ex);}}}公共 PrintUIWindow(JFrame f) {帧打印 = f;}公共静态无效主要(字符串参数[]){UIManager.put("swing.boldMetal", Boolean.FALSE);JFrame f = new JFrame("打印 UI 示例");f.addWindowListener(new WindowAdapter() {公共无效 windowClosing(WindowEvent e) {System.exit(0);}});//打印框架设计开始JFrame frame = new JFrame("打印 UI 示例");JLabel label11=new JLabel("销售单",JLabel.CENTER);JLabel label21=new JLabel("客户名称:",JLabel.LEFT);JLabel label31=new JLabel("购买日期:",JLabel.LEFT);JLabel label41=new JLabel("买书:",JLabel.LEFT);JLabel label51=new JLabel("编号:",JLabel.LEFT);JLabel label61=new JLabel("总价:",JLabel.LEFT);label11.setFont(new Font("Courier New", Font.BOLD, 13));label21.setFont(new Font("Courier New", Font.BOLD, 13));label31.setFont(new Font("Courier New", Font.BOLD, 13));label41.setFont(new Font("Courier New", Font.BOLD, 13));label51.setFont(new Font("Courier New", Font.BOLD, 13));label61.setFont(new Font("Courier New", Font.BOLD, 13));JPanel 面板 1=新 JPanel();panel1.setLayout(new GridLayout(6,1));panel1.add(label11);panel1.add(label21);panel1.add(label31);panel1.add(label41);panel1.add(label51);panel1.add(label61);frame.setSize(300,300);frame.setLocationRelativeTo(null);frame.add(panel1,BorderLayout.CENTER);panel1.setBackground(Color.WHITE);frame.setResizable(false);frame.setVisible(true);//打印框架设计结束//第一帧设计开始JLabel label1=new JLabel("销售单",JLabel.CENTER);JLabel label2=new JLabel("客户名称:",JLabel.LEFT);JLabel label3=new JLabel("购买日期:",JLabel.LEFT);JLabel label4=new JLabel("买书:",JLabel.LEFT);JLabel label5=new JLabel("编号:",JLabel.LEFT);JLabel label6=new JLabel("总价:",JLabel.LEFT);label1.setFont(new Font("Courier New", Font.BOLD, 13));label2.setFont(new Font("Courier New", Font.BOLD, 13));label3.setFont(new Font("Courier New", Font.BOLD, 13));label4.setFont(new Font("Courier New", Font.BOLD, 13));label5.setFont(new Font("Courier New", Font.BOLD, 13));label6.setFont(new Font("Courier New", Font.BOLD, 13));JButton printButton = new JButton("打印这个窗口");//打印按钮代码printButton.addActionListener(new PrintUIWindow(frame));JPanel 面板=新 JPanel();panel.setLayout(new GridLayout(6,1));panel.add(label1);panel.add(label2);panel.add(label3);panel.add(label4);panel.add(label5);panel.add(label6);f.setSize(300,300);f.setLocationRelativeTo(null);f.add(panel,BorderLayout.CENTER);f.add(printButton,BorderLayout.SOUTH);panel.setBackground(Color.WHITE);f.setResizable(false);f.setVisible(true);}}

解决方案

我是多么讨厌打印组件,说真的,要么学习手工完成,要么使用 Jasper Reports 之类的东西.

你有一系列问题...

  1. 组件只能有一个父级,因此当您创建第二个窗口并向其中添加组件时,您就是从第一个窗口中删除它们;
  2. 你不能绘制一个不可见的组件;
  3. 您确实不应该打印框架,最好打印面板;
  4. 除非它已在屏幕上实现,否则您将负责确保在打印之前正确布局组件

您真的不想打印框架,您实际上想打印面板,它只是简单得多,而且您没有得到框架.如果您还想打印框架,则需要使框架可见.

因此,基于

因此,基本上,这添加了一个简单的工厂方法来创建基本面板.这将创建此面板的两个实例,一个用于打印,一个用于显示(从技术上讲,您可以使用一个,但您明白了).

打印过程将在打印时更新面板的布局,以确保其内容正确放置,以便实际呈现.

import java.awt.BorderLayout;导入 java.awt.Color;导入java.awt.Font;导入 java.awt.Graphics;导入 java.awt.Graphics2D;导入 java.awt.GridLayout;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 java.awt.print.PageFormat;导入 java.awt.print.Printable;导入静态 java.awt.print.Printable.NO_SUCH_PAGE;导入静态 java.awt.print.Printable.PAGE_EXISTS;导入 java.awt.print.PrinterException;导入 java.awt.print.PrinterJob;导入 javax.swing.JButton;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JPanel;导入 javax.swing.UIManager;类 PrintUIWindow 实现可打印,ActionListener {JPanel frameToPrint;布尔填充=假;公共 int print(Graphics g, PageFormat pf, int page) 抛出打印机异常 {如果(页面 > 0){返回 NO_SUCH_PAGE;}双宽度 = (int) Math.floor(pf.getImageableWidth());双倍高度 = (int) Math.floor(pf.getImageableHeight());如果(!填充){width = Math.min(width, frameToPrint.getPreferredSize().width);height = Math.min(height, frameToPrint.getPreferredSize().height);}System.out.println(width + "x" + height);Graphics2D g2d = (Graphics2D) g;g2d.translate(pf.getImageableX(), pf.getImageableY());System.out.println(width + "x" + height);frameToPrint.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height));if (frameToPrint.getParent() == null) {frameToPrint.addNotify();}frameToPrint.validate();frameToPrint.doLayout();frameToPrint.printAll(g2d);if (frameToPrint.getParent() != null) {frameToPrint.removeNotify();}返回 PAGE_EXISTS;}公共无效actionPerformed(ActionEvent e){PrinterJob 作业 = PrinterJob.getPrinterJob();job.setPrintable(this);boolean ok = job.printDialog();如果(好){尝试 {作业.print();} 捕捉(打印机异常前){System.out.println(ex);}}}公共 PrintUIWindow(JPanel f) {帧打印 = f;}公共静态无效力布局(JPanel面板){if (panel.getParent() == null) {面板.addNotify();}面板.验证();面板.doLayout();if (panel.getParent() != null) {panel.removeNotify();}}公共静态JPanel makePanel(){JLabel label11 = new JLabel("销售单", JLabel.LEFT);JLabel label21 = new JLabel("客户名称:", JLabel.LEFT);JLabel label31 = new JLabel("购买日期:", JLabel.LEFT);JLabel label41 = new JLabel("买书:", JLabel.LEFT);JLabel label51 = new JLabel("编号:", JLabel.LEFT);JLabel label61 = new JLabel("总价:", JLabel.LEFT);label11.setFont(new Font("Courier New", Font.BOLD, 13));label21.setFont(new Font("Courier New", Font.BOLD, 13));label31.setFont(new Font("Courier New", Font.BOLD, 13));label41.setFont(new Font("Courier New", Font.BOLD, 13));label51.setFont(new Font("Courier New", Font.BOLD, 13));label61.setFont(new Font("Courier New", Font.BOLD, 13));JPanel 面板 1 = 新 JPanel();panel1.setLayout(new GridLayout(6, 1));panel1.add(label11);panel1.add(label21);panel1.add(label31);panel1.add(label41);panel1.add(label51);panel1.add(label61);panel1.setBackground(Color.WHITE);返回面板1;}公共静态无效主要(字符串参数[]){UIManager.put("swing.boldMetal", Boolean.FALSE);JFrame f = new JFrame("打印 UI 示例");JButton printButton = new JButton("打印这个窗口");JPanel toPrint = makePanel();System.out.println(toPrint.getPreferredSize());强制布局(toPrint);System.out.println(toPrint.getPreferredSize());printButton.addActionListener(new PrintUIWindow(toPrint));JPanel 面板 = makePanel();f.add(面板, BorderLayout.CENTER);f.add(printButton, BorderLayout.SOUTH);f.pack();f.setLocationRelativeTo(null);f.setVisible(true);System.out.println(panel.getPreferredSize());System.out.println(panel.getSize());}}

I create a Swing application with 2 JFrame windows and I want to 1st frame as main page. I set print button in 1st frame to print 2nd frame.

How can I print the second frame with frame.setVisible(false);? How can I solve it?

I put my code below:

package printuiwindow;

    /**
     *
     * @author Saravanan Ponnusamy
     */
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import java.awt.print.*;

     class PrintUIWindow implements Printable, ActionListener {


    JFrame frameToPrint;

    public int print(Graphics g, PageFormat pf, int page) throws
                                                        PrinterException {

        if (page > 0) {
            return NO_SUCH_PAGE;
        }

        Graphics2D g2d = (Graphics2D)g;
        g2d.translate(pf.getImageableX(), pf.getImageableY()-55);

        frameToPrint.print(g);

        return PAGE_EXISTS;
    }

    public void actionPerformed(ActionEvent e) {
         PrinterJob job = PrinterJob.getPrinterJob();
         job.setPrintable(this);
         boolean ok = job.printDialog();
         if (ok) {
             try {
                  job.print();
             } catch (PrinterException ex) {
 System.out.println(ex);
             }
         }
    }

    public PrintUIWindow(JFrame f) {
        frameToPrint = f;
    }

    public static void main(String args[]) {
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        JFrame f = new JFrame("Print UI Example");
        f.addWindowListener(new WindowAdapter() {
           public void windowClosing(WindowEvent e) {System.exit(0);}
        });
 //Printing frame design start


        JFrame frame = new JFrame("Print UI Example");
         JLabel label11=new JLabel("Selling Bill",JLabel.CENTER);
        JLabel label21=new JLabel("Customer Name :",JLabel.LEFT);
        JLabel label31=new JLabel("Buying Date :",JLabel.LEFT);
        JLabel label41=new JLabel("Book Buyed :",JLabel.LEFT);
        JLabel label51=new JLabel("Number :",JLabel.LEFT);
        JLabel label61=new JLabel("Total Price :",JLabel.LEFT);
         label11.setFont(new Font("Courier New", Font.BOLD, 13));
        label21.setFont(new Font("Courier New", Font.BOLD, 13));
        label31.setFont(new Font("Courier New", Font.BOLD, 13));
        label41.setFont(new Font("Courier New", Font.BOLD, 13));
        label51.setFont(new Font("Courier New", Font.BOLD, 13));
        label61.setFont(new Font("Courier New", Font.BOLD, 13));
 JPanel panel1=new JPanel();
 panel1.setLayout(new GridLayout(6,1));
        panel1.add(label11);
        panel1.add(label21);
        panel1.add(label31);
        panel1.add(label41);
        panel1.add(label51);
        panel1.add(label61);
        frame.setSize(300,300);
        frame.setLocationRelativeTo(null);
        frame.add(panel1,BorderLayout.CENTER);  
        panel1.setBackground(Color.WHITE);
        frame.setResizable(false);
        frame.setVisible(true);
    //printing frame design end    

//first frame design start
        JLabel label1=new JLabel("Selling Bill",JLabel.CENTER);
        JLabel label2=new JLabel("Customer Name :",JLabel.LEFT);
        JLabel label3=new JLabel("Buying Date :",JLabel.LEFT);
        JLabel label4=new JLabel("Book Buyed :",JLabel.LEFT);
        JLabel label5=new JLabel("Number :",JLabel.LEFT);
        JLabel label6=new JLabel("Total Price :",JLabel.LEFT);

        label1.setFont(new Font("Courier New", Font.BOLD, 13));
        label2.setFont(new Font("Courier New", Font.BOLD, 13));
        label3.setFont(new Font("Courier New", Font.BOLD, 13));
        label4.setFont(new Font("Courier New", Font.BOLD, 13));
        label5.setFont(new Font("Courier New", Font.BOLD, 13));
        label6.setFont(new Font("Courier New", Font.BOLD, 13));

        JButton printButton = new JButton("Print This Window");

        //print button code
        printButton.addActionListener(new PrintUIWindow(frame));
        JPanel panel=new JPanel();

        panel.setLayout(new GridLayout(6,1));
        panel.add(label1);
        panel.add(label2);
        panel.add(label3);
        panel.add(label4);
        panel.add(label5);
        panel.add(label6);
        f.setSize(300,300);
        f.setLocationRelativeTo(null);
        f.add(panel,BorderLayout.CENTER);
        f.add(printButton,BorderLayout.SOUTH);
        panel.setBackground(Color.WHITE);
        f.setResizable(false);
        f.setVisible(true);
    }
}

解决方案

How I hate printing components, seriously, either learn to do it by hand or use something like Jasper Reports.

You have a series of issues...

  1. Components can only have one parent, so when you create your second window and add the components to it, you're removing them from the first window;
  2. You can't paint an invisible component;
  3. You really shouldn't be printing the frame anyway, better to print the panel instead;
  4. Unless it's been realised on the screen, you'll be responsible for ensure that the component is properly laid out before it's printed

You really don't want to print the frame, you actually want to print the panel instead, it's just a lot simpler and you don't get the frame. If you want to print the frame as well, you will need to make the frame visible.

So, based on this previous answer

So, basically, this adds a simple factory method to create the base panel. This will make two instances of this panel, one to print and one to display (technically you could use one, but you get the idea).

The printing process will update the layout of the panel while it's printing to make sure that it's contents are properly laid, so that they are actually rendered.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import static java.awt.print.Printable.NO_SUCH_PAGE;
import static java.awt.print.Printable.PAGE_EXISTS;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;

class PrintUIWindow implements Printable, ActionListener {

    JPanel frameToPrint;
    boolean fill = false;

    public int print(Graphics g, PageFormat pf, int page) throws
                    PrinterException {

        if (page > 0) {
            return NO_SUCH_PAGE;
        }
        double width = (int) Math.floor(pf.getImageableWidth());
        double height = (int) Math.floor(pf.getImageableHeight());

        if (!fill) {

            width = Math.min(width, frameToPrint.getPreferredSize().width);
            height = Math.min(height, frameToPrint.getPreferredSize().height);

        }

        System.out.println(width + "x" + height);
        Graphics2D g2d = (Graphics2D) g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());
        System.out.println(width + "x" + height);
        frameToPrint.setBounds(0, 0, (int) Math.floor(width), (int) Math.floor(height));
        if (frameToPrint.getParent() == null) {
            frameToPrint.addNotify();
        }
        frameToPrint.validate();
        frameToPrint.doLayout();
        frameToPrint.printAll(g2d);
        if (frameToPrint.getParent() != null) {
            frameToPrint.removeNotify();
        }

        return PAGE_EXISTS;
    }

    public void actionPerformed(ActionEvent e) {
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(this);
        boolean ok = job.printDialog();
        if (ok) {
            try {
                job.print();
            } catch (PrinterException ex) {
                System.out.println(ex);
            }
        }
    }

    public PrintUIWindow(JPanel f) {
        frameToPrint = f;
    }

    public static void forceLayout(JPanel panel) {
        if (panel.getParent() == null) {
            panel.addNotify();
        }
        panel.validate();
        panel.doLayout();
        if (panel.getParent() != null) {
            panel.removeNotify();
        }
    }

    public static JPanel makePanel() {
        JLabel label11 = new JLabel("Selling Bill", JLabel.LEFT);
        JLabel label21 = new JLabel("Customer Name :", JLabel.LEFT);
        JLabel label31 = new JLabel("Buying Date :", JLabel.LEFT);
        JLabel label41 = new JLabel("Book Buyed :", JLabel.LEFT);
        JLabel label51 = new JLabel("Number :", JLabel.LEFT);
        JLabel label61 = new JLabel("Total Price :", JLabel.LEFT);
        label11.setFont(new Font("Courier New", Font.BOLD, 13));
        label21.setFont(new Font("Courier New", Font.BOLD, 13));
        label31.setFont(new Font("Courier New", Font.BOLD, 13));
        label41.setFont(new Font("Courier New", Font.BOLD, 13));
        label51.setFont(new Font("Courier New", Font.BOLD, 13));
        label61.setFont(new Font("Courier New", Font.BOLD, 13));
        JPanel panel1 = new JPanel();
        panel1.setLayout(new GridLayout(6, 1));
        panel1.add(label11);
        panel1.add(label21);
        panel1.add(label31);
        panel1.add(label41);
        panel1.add(label51);
        panel1.add(label61);
        panel1.setBackground(Color.WHITE);
        return panel1;
    }

    public static void main(String args[]) {
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        JFrame f = new JFrame("Print UI Example");

        JButton printButton = new JButton("Print This Window");

        JPanel toPrint = makePanel();
        System.out.println(toPrint.getPreferredSize());
        forceLayout(toPrint);
        System.out.println(toPrint.getPreferredSize());

        printButton.addActionListener(new PrintUIWindow(toPrint));
        JPanel panel = makePanel();
        f.add(panel, BorderLayout.CENTER);
        f.add(printButton, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);

        System.out.println(panel.getPreferredSize());
        System.out.println(panel.getSize());
    }
}

这篇关于使用 setVisible(false) 打印 JFrame的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆