主页 >> 程序猿的东西 >> Java生成表格图片

Java生成表格图片

python生成表格图片非常简单,直接用plot方法就可以搞定了。但是Java做这事就麻烦得多,目前ChatGPT给出的方案全部是基于swing类实现的,原理是先构造一个UI窗口来显示你的信息,然后再对窗口截图。如果是API开发人员做这事等于在做前端开发,下面是代码示例。

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
public class generateImage {
    public static void tableImage(JSONArray jsonArray, String outputPath) throws IOException {
        // 解析JSON数据
        Object[][] data = new Object[jsonArray.size()+1][4];
        Object[] columnNames = {"比例", "持有者", "金额", "xid"};
        data[0] = columnNames;
        for (int i = 1; i <= jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i-1);
            data[i][0] = jsonObject.getDouble("fundedRatioNum");
            data[i][1] = jsonObject.getString("inv");
            data[i][2] = jsonObject.getDouble("subConam");
            data[i][3] = jsonObject.getString("xid");
        }

        // 创建JTable
        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        table.setRowHeight(30);

        for (int column = 0; column < table.getColumnCount(); column++) {
            TableColumn tableColumn = table.getColumnModel().getColumn(column);
            int preferredWidth = tableColumn.getMinWidth();
            int maxWidth = tableColumn.getMaxWidth();

            for (int row = 0; row < table.getRowCount(); row++) {
                TableCellRenderer cellRenderer = table.getCellRenderer(row, column);
                Component c = table.prepareRenderer(cellRenderer, row, column);
                int width = c.getPreferredSize().width + table.getIntercellSpacing().width;
                preferredWidth = Math.max(preferredWidth, width);

                //  We've exceeded the maximum width, no need to check other rows
                if (preferredWidth >= maxWidth) {
                    preferredWidth = maxWidth;
                    break;
                }
            }

            tableColumn.setPreferredWidth(preferredWidth);
        }

        JPanel panel = new JPanel();
        panel.add(table);

        JFrame frame = new JFrame();
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);

        BufferedImage image = new BufferedImage(panel.getWidth(), panel.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();
        panel.paint(g);
        try {
            // Write the BufferedImage to a file
            ImageIO.write(image, "png", new File("table.png"));
        } catch (IOException e) {
            System.out.println("fail");

            e.printStackTrace();
        }

    }
}

这段代码直接执行是没问题的,但是如果集成在Spring Boot里面会报一个HeadlessException错误,大概原因是不可以无头模式渲染这些窗口。需要把Spring Boot入口方法改成下面这样,但是这样带来新的问题是这个窗口你不关就会一直显示在那里,但是应该有一些方法在生成图片之后自动关掉的,但是这总归是一件非常扯的事情。

// SpringApplication.run(App.class, args);        
SpringApplicationBuilder builder = new SpringApplicationBuilder(App.class);
builder.headless(false);
ConfigurableApplicationContext context = builder.run(args);

最终我还是放弃了用API生成图片的天真想法。