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生成图片的天真想法。