当OP请求代码示例时,我提供了有关在Java API or Tool to convert tabular data into PNG image file上捕获表格数据图像的建议。原来比我想象的要难! JTable header 从代码写入的PNG中消失。
PNG

屏幕截图

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

import javax.imageio.ImageIO;
import java.io.File;

class TableImage {

    public static void main(String[] args) throws Exception {
        Object[][] data = {
            {"Hari", new Integer(23), new Double(78.23), new Boolean(true)},
            {"James", new Integer(23), new Double(47.64), new Boolean(false)},
            {"Sally", new Integer(22), new Double(84.81), new Boolean(true)}
        };

        String[] columns = {"Name", "Age", "GPA", "Pass"};

        JTable table = new JTable(data, columns);
        JScrollPane scroll = new JScrollPane(table);
        JPanel p = new JPanel(new BorderLayout());
        p.add(scroll,BorderLayout.CENTER);

        JOptionPane.showMessageDialog(null, p);

        BufferedImage bi = new BufferedImage(
            (int)p.getSize().getWidth(),
            (int)p.getSize().getHeight(),
            BufferedImage.TYPE_INT_RGB
            );

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

        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
        ImageIO.write(bi,"png",new File("table.png"));
    }
}
注意:我检查了camickr的Screen Image类,并包括了对doLayout(Component)方法的调用。如果尚未在屏幕上实现Component,但对该代码没有影响(在尝试呈现它之前,该表会在选项 Pane 中弹出包含表的面板),则该方法很有用。
为了使表头呈现,需要什么?
更新1
换线..
        p.paint(g);
..to(带有适当的导入)
        p.paint(g);
        JTableHeader h = table.getTableHeader();
        h.paint(g);
..生产..

我会继续调整它。
更新2
kleopatra(策略1)和camickr(策略2)都提供了一个答案,两者都有效,而且都不要求将JTable添加到虚拟组件(这是一个巨大的IMO)。
策略2会裁剪(或扩展)为“仅显示表格”,而第一种策略将捕获包含表格的面板。如果该表包含许多条目,这会出现问题,并显示带有滚动条的截断表的图像。
尽管可能会进一步调整策略1来解决此问题,但我真的很喜欢策略2的简洁性,所以它很受人欢迎。
正如kleopatra指出的那样,不需要“调整”。所以我会再试一次..
更新3
这是camickr和kleopatra提出的方法产生的图像。我会说两次,但是在我看来,它们是相同的(尽管我没有进行逐像素比较)。
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import java.io.File;

class TableImage {

    String[] columns = {"Name", "Age", "GPA", "Pass"};
    /** Any resemblance to persons living or dead is purely incidental. */
    Object[][] data = {
        {"André", new Integer(23), new Double(47.64), new Boolean(false)},
        {"Jeanie", new Integer(23), new Double(84.81), new Boolean(true)},
        {"Roberto", new Integer(22), new Double(78.23), new Boolean(true)}
    };

    TableImage() {
    }

    public JTable getTable() {
        JTable table = new JTable(data, columns);
        table.setGridColor(new Color(115,52,158));
        table.setRowMargin(5);
        table.setShowGrid(true);

        return table;
    }

    /** Method courtesy of camickr.
    https://stackoverflow.com/questions/7369814/why-does-the-jtable-header-not-appear-in-the-image/7375655#7375655
    Requires ScreenImage class available from..
    http://tips4java.wordpress.com/2008/10/13/screen-image/ */
    public BufferedImage getImage1(JTable table) {
        JScrollPane scroll = new JScrollPane(table);

        scroll.setColumnHeaderView(table.getTableHeader());
        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        JPanel p = new JPanel(new BorderLayout());
        p.add(scroll, BorderLayout.CENTER);

        BufferedImage bi = ScreenImage.createImage(p);
        return bi;
    }

    /** Method courtesy of kleopatra.
    https://stackoverflow.com/questions/7369814/why-does-the-jtable-header-not-appear-in-the-image/7372045#7372045 */
    public BufferedImage getImage2(JTable table) {
        JScrollPane scroll = new JScrollPane(table);

        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        JPanel p = new JPanel(new BorderLayout());
        p.add(scroll, BorderLayout.CENTER);

        // 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(), p.getHeight(), BufferedImage.TYPE_INT_RGB);

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

        return bi;
    }

    public void writeImage(BufferedImage image, String name) throws Exception {
        ImageIO.write(image,"png",new File(name + ".png"));
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        TableImage ti = new TableImage();
        JTable table;
        BufferedImage bi;

        table = ti.getTable();
        bi = ti.getImage1(table);
        ti.writeImage(bi, "1");
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));

        table = ti.getTable();
        bi = ti.getImage2(table);
        ti.writeImage(bi, "2");
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
    }
}
两者都达到了目标。使用camickr的方法,您可以利用ScreenImage API的更多功能。使用kleopatra的方法-大约十二行(减去注释和空白)纯J2SE。
虽然ScreenImage是我将来会使用并推荐的一类,但是使用核心J2SE的另一种方法是在这种情况下可能使用的方法。
因此,尽管“滴答声”将留在camickr上,但赏金将用于kleopatra。

最佳答案



ScreenImage可以处理此问题。

您必须手动将标题添加到滚动 Pane 。

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

import javax.imageio.ImageIO;
import java.io.File;

class TableImage {

    public static void main(String[] args) throws Exception {
        Object[][] data = {
            {"Hari", new Integer(23), new Double(78.23), new Boolean(true)},
            {"James", new Integer(23), new Double(47.64), new Boolean(false)},
            {"Sally", new Integer(22), new Double(84.81), new Boolean(true)}
        };

        String[] columns = {"Name", "Age", "GPA", "Pass"};

        JTable table = new JTable(data, columns);
        JScrollPane scroll = new JScrollPane(table);

        scroll.setColumnHeaderView(table.getTableHeader());
        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        JPanel p = new JPanel(new BorderLayout());
        p.add(scroll, BorderLayout.CENTER);

        BufferedImage bi = ScreenImage.createImage(p);

        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
        ImageIO.write(bi,"png",new File("table.png"));
    }
}

注意:Kleopatra建议在面板上使用addNotify()不适用于ScreenImage。 addNotify()方法使组件displayable和ScreenImage代码仅将组件布局为不可显示的组件。我可能会考虑使其更通用。

10-04 10:15