1

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);
    }
}
  • See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) – Andrew Thompson Oct 27 '17 at 07:05
  • So, based on the code you have available, you have two frames, both of which are visible...is this deliberate? – MadProgrammer Oct 27 '17 at 07:05
  • Your code does not reveal what you have described in your question. However, use 2ndframe.setvisibile(true) in the button handler if you want to display the frame by clicking the button. – Anastasios Vlasopoulos Oct 27 '17 at 07:13
  • 1
    So, you have a series of compounding problems. 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 – MadProgrammer Oct 27 '17 at 07:14
  • As a general piece of advice, not print this way, printing is a complicated and nothing like working with graphics on the screen – MadProgrammer Oct 27 '17 at 07:41

1 Answers1

3

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

The windowThe form

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());
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you friends I Got it Now I am Understand we can't paint an invisible component. so I have to print that Jpanel and also add that panel into the first panel Thankyou very much guys – SARAVANAN PONNUSAMY Oct 27 '17 at 07:55