4

I'm working on printing a series of JPanels to a Printable, the basic printing interface that supplies a Graphics object that you draw what you want printed. If I have a "live" JPanel, that is in the UI somewhere, everything works great.

However, if I create a JPanel and never add it to the UI, printAll() appears to do nothing at all. Reducing the code to a SSCCE:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SSCCEPaintInvisible
{
    public static void main(String[] args)
    {
        /* Create an JPanel with a JLabel */
        JPanel panel = new JPanel();
        //panel.setLayout(new FlowLayout());
        JLabel label = new JLabel("Hello World");
        panel.add(label);
        //label.invalidate();
        //panel.invalidate();

        /* Record a picture of the panel */
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();

        /* Draw something to ensure we're drawing */
        g.setColor(Color.BLACK);
        g.drawLine(0, 0, 100, 100);

        /* Attempt to draw the panel we created earlier */ 
        panel.paintAll(g);  // DOES NOTHING. :(

        /* Display a frame to test if the graphics was captured */
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label2 = new JLabel( new ImageIcon(image) );
        frame.add(label2);
        frame.pack();

        frame.setVisible(true);
            // shows ONLY the black line we drew in the Graphics
    }
}

If I create a JFrame for the panel and add the panel to the JFrame and make the JFrame visible before the call to paintAll(), the code captures the UI to the Graphic as expected. Of course, this flashes a JFrame on your screen to print it.

Is there any way to render a JPanel that has never been added to the UI into a Graphics object? Thanks!

mKorbel
  • 109,525
  • 20
  • 134
  • 319
utopianheaven
  • 1,267
  • 7
  • 18

1 Answers1

3

From the tips of the answer of @Kleopatra.

SSCCEPaintInvisible

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class SSCCEPaintInvisible
{
    public static void main(String[] args)
    {
        /* Create an JPanel with a JLabel */
        JPanel panel = new JPanel();

        JLabel label = new JLabel("Hello World");
        panel.add(label);
        // Next 3 are very important!
        panel.setSize(panel.getPreferredSize());
        panel.addNotify();
        panel.doLayout();

        /* Record a picture of the panel */
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();

        /* Draw something to ensure we're drawing */
        g.setColor(Color.BLACK);
        g.drawLine(0, 0, 100, 100);

        /* Attempt to draw the panel we created earlier */
        panel.paintAll(g);  // DOES NOTHING. :(

        /* Display a frame to test if the graphics was captured */
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel label2 = new JLabel( new ImageIcon(image) );
        frame.add(label2);
        frame.pack();

        frame.setVisible(true);
            // shows ONLY the black line we drew in the Graphics
    }
}

As pointed out by @GagandeepBali, this GUI is not created on the EDT. Results will be unpredictable if changes to a GUI are not done on the EDT. See Concurrency in Swing & particularly Initial Threads for more details.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Wish I could have that knowledge one day, to actually downvote your post :-), but rather doubt that, that the day is soon coming. But hoping as I learn new things each day :-) – nIcE cOw Jan 08 '13 at 13:59
  • 3
    @GagandeepBali *"to actually downvote your post"* (chuckle) You would be surprised at some of the things I post that apparently slipped 'beneath your radar'. Take horrible code, fix one or two lines and dump it back as is (is sometimes my philosophy). To the OP - don't be confused, your code was not 'horrible' - but much of the code posted around here in questions **is.** – Andrew Thompson Jan 08 '13 at 14:04
  • @GagandeepBali (and utopianheaven) See final paragraph. :) – Andrew Thompson Jan 08 '13 at 14:05