Why does the JTable header not appear in the image?

that was a tough one

Was puzzled that that header didn’t show up on the image at all: it wasn’t clipped or something, it wasn’t painted at all. The reason for that is .. that at the time of painting the panel to the image, the header is no longer part of the hierarchy. When closing the optionPane, table.removeNotify removes the header. For adding it again, call addNotify, as in this snippet:

    JScrollPane scroll = new JScrollPane(table);
    JPanel p = new JPanel(new BorderLayout());
    p.add(scroll, BorderLayout.CENTER);
    JOptionPane.showMessageDialog(null, p);
    table.addNotify();
    p.doLayout();
    BufferedImage bi = new BufferedImage(p.getWidth() + 100,
            p.getHeight() + 100, BufferedImage.TYPE_INT_RGB);

    Graphics g = bi.createGraphics();
    p.paint(g);
    g.dispose();

[solved in edit] What I still don’t understand why the panel shows up empty without first having been shown in the optionPane – typically some combination of ..

   p.doLayout();
   p.setSize(p.getPreferredSize()) 

… will do

Edit

last confusion solved: to force a recursive re-layout of the pane, all container along the line must be driven into believing they have a peer – validate is optimized to do nothing if not. Doing the addNotify on the panel (instead of on the table) plus validate does the trick

    //        JOptionPane.showMessageDialog(null, p);
    // without having been shown, fake a all-ready
    p.addNotify();
    // manually size to pref
    p.setSize(p.getPreferredSize());
    // validate to force recursive doLayout of children
    p.validate();
    BufferedImage bi = new BufferedImage(p.getWidth() + 100,
            p.getHeight() + 100, BufferedImage.TYPE_INT_RGB);

    Graphics g = bi.createGraphics();
    p.paint(g);
    g.dispose();

    JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));

Not tested for side-effects.

Edit 2

Just grumbling a bit about the..

strategy 1 might be further tweaked to get around that [truncated table column]

Actually there is no tweak needed (or the the same tweak needed as for ScreenImage, depends on what you consider a tweak 🙂 – both require to make the JScrollPane not do its job by setting the table’s prefViewportSize, the exact same line in both:

    // strategy 1
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    p.addNotify();

    // strategy 2
    scroll.setColumnHeaderView(table.getTableHeader());
    table.setPreferredScrollableViewportSize(table.getPreferredSize());

Leave a Comment