gpt4 book ai didi

java - 为什么 JTable 表头没有出现在图像中?

转载 作者:IT老高 更新时间:2023-10-28 21:12:15 24 4
gpt4 key购买 nike

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

PNG

PNG

屏幕截图

enter image description here

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);

..产生..

2nd try

我会继续调整它。

更新 2

kleopatra (strategy 1) 和 camickr (strategy 2) 都提供了答案,两者都有效,并且都不需要添加 JTable到一个虚拟组件(这是一个巨大的 hack IMO)。

虽然策略 2 将裁剪(或扩展)为“仅表格”,第一个策略将捕获包含表格的面板。如果表格包含许多条目,这将成为问题,显示带有滚动条的截断表格的图像。

虽然策略 1 可能会进一步调整以解决这个问题,但我真的很喜欢策略 2 的简洁明了,所以它很受欢迎。

正如 kleopatra 所指出的,不需要“调整”。所以我会再试一次..

更新 3

这是由camickr和kleopatra提出的方法产生的图像。我会放两次,但在我看来,它们是相同的(尽管我没有进行逐像素比较)。

JTable in Nimbus PLAF

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 的另一种方法是我可能会在这种确切情况下使用的方法。

因此,虽然 'tick' 将留在 camickr,但赏金将留在 kleopatra。

最佳答案

这是一个艰难的过程

对于该标题根本没有出现在图像上感到困惑:它没有被剪裁或其他什么,它根本没有被绘制。原因是..在将面板绘制到图像时,标题不再是层次结构的一部分。关闭 optionPane 时,table.removeNotify 会删除标题。要再次添加它,请调用 addNotify,如以下代码段所示:

    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();

[在编辑中解决]我仍然不明白为什么面板在没有首先显示在 optionPane 的情况下显示为空 - 通常是 ..的某种组合。

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

...会的

编辑

最后一个困惑解决了:为了强制对 Pane 进行递归重新布局,必须驱使沿线的所有容器相信它们有一个对等点 - 如果没有,验证被优化为什么都不做。在面板上(而不是在 table 上)执行 addNotify 加上验证就可以了

    //        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)));

未测试副作用。

编辑 2

只是有点提示……

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

实际上不需要调整(或需要与 ScreenImage 相同的调整,取决于您认为调整的内容:) - 两者都需要通过设置 JScrollPane not 完成其工作表的 prefViewportSize,两者完全相同:

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

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

关于java - 为什么 JTable 表头没有出现在图像中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7369814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com