Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么JTable标头不出现在图像中?_Java_Image_Swing_Jtable - Fatal编程技术网

Java 为什么JTable标头不出现在图像中?

Java 为什么JTable标头不出现在图像中?,java,image,swing,jtable,Java,Image,Swing,Jtable,当OP请求一个代码示例时,我正在提供关于在上捕获表格数据图像的建议。结果比我想象的要难!JTable头从代码编写的PNG中消失 巴布亚新几内亚 截屏 注意:我检查了camickr的类,包括对doLayout(Component)方法的调用。如果组件从未在屏幕上实现,但对该代码没有影响(在尝试渲染之前,会在选项窗格中弹出包含该表的面板),则该方法非常有用 要获得要呈现的表头,需要什么 更新1 换行 p.paint(g); …到(具有适当的导入) …生产 我会继续调整它 更新

当OP请求一个代码示例时,我正在提供关于在上捕获表格数据图像的建议。结果比我想象的要难!
JTable
头从代码编写的PNG中消失

巴布亚新几内亚

截屏

注意:我检查了camickr的类,包括对
doLayout(Component)
方法的调用。如果
组件
从未在屏幕上实现,但对该代码没有影响(在尝试渲染之前,会在选项窗格中弹出包含该表的面板),则该方法非常有用

要获得要呈现的表头,需要什么

更新1 换行

        p.paint(g);
…到(具有适当的导入)

…生产

我会继续调整它

更新2 kleopatra(策略1)和camickr(策略2)分别提供了一个答案,这两个答案都有效,并且都不需要将
JTable
添加到虚拟组件(这是一个巨大的漏洞)

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

虽然策略1可能会被进一步调整以避开这个问题,但我真的很喜欢策略2简洁的简洁性,因此它得到了支持

正如克利奥帕特拉所指出的,不需要“调整”。所以我会再试一次

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

两者都实现了目标。使用camickr的方法,您可以进一步利用ScreenImage API的强大功能。使用kleopatra的方法-大约十几行纯J2SE代码(减去注释和空白)

虽然ScreenImage是我将来将使用和推荐的一个类,但另一种使用核心J2SE的方法可能就是我在这种情况下可能使用的方法


因此,虽然“勾号”将保留在camickr上,但赏金将转移到kleopatra。

在打印组件之前尝试禁用组件(或全局)上的双缓冲(
c.setDoubleBuffered(false)
)。显然它有一种效果:)(见和)


请,这不是答案,只是评论和一点点…:-)

@安德鲁·汤普森,如果我正确理解的话,只需参考
J/Components
是in/pass
Graphics2D g2=(Graphics2D)g和未被接受引用/派生的
TableHeader….
可能(我懒得检查)API中的某些内容

代码截取显示:-)


手动将您的
JPanel
添加到您自己创建的
JFrame
,而不仅仅是JOptionPane使用的,似乎可以解决这个问题

如果需要,引入
JFrame
可以跳过初始对话框显示

// ...snip 

JOptionPane.showMessageDialog(null, p);

JFrame frame = new JFrame();
frame.setContentPane(p);
frame.pack();

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

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

JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
ImageIO.write(bi,"png",new File("table.png"));
那是一个艰难的时刻

令人困惑的是,头球根本没有出现在图片上:它没有被剪掉或什么的,它根本没有被画出来。原因是。。在将面板绘制到图像时,标题不再是层次的一部分。关闭选项窗格时,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();
[在编辑中解决]我仍然不明白为什么面板显示为空,而没有首先显示在选项窗格中-通常是一些组合

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

编辑

最后解决的困惑是:为了强制递归地重新布局窗格,必须让所有容器相信它们有一个对等验证,否则将优化为什么也不做。在面板上(而不是在表上)执行addNotify加上validate就可以了

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

只是有点抱怨

策略1可能会进一步调整,以绕过[截断的表列]

实际上不需要TWIWE(或者对于ScreenImage需要的相同的调整,取决于您考虑的一个调整:)-两个都需要通过设置表的PrfVIEWTRAWSIZE使JScRunPANT不做它的工作,在两个完全相同的行:

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

    // strategy 2
    scroll.setColumnHeaderView(table.getTableHeader());
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
该线程并不要求在不显示表的情况下呈现表,但这是最终目标

ScreenImage处理这个问题

必须手动将标题添加到滚动窗格中

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()方法使组件
可显示
,而ScreenImage代码将仅为不可显示的组件布局组件。我可能会考虑让这更一般化。

像这样的问题让我不敢使用Swing。@忽必烈这是一个奇怪的角落案例,你是一只胆小鬼。。)顺便说一句-试试AWT。“老兄,我的头球呢?”-老兄,我不知道!你上次把它放在哪里了?:-)@斯蒂芬:这是电影《老兄!我的车在哪里》中的双关语:@Suraj也许这是斯蒂芬的挖苦,大意是我不应该用双关语。很高兴我没有使用被认为是“老兄,我的头在哪里?”)的变体调用
c.setDoubleBuffered(false)
没有明显的效果。也许这纯粹是与印刷有关。这一点很好。这个帖子并不要求你在不显示表格的情况下呈现表格,但这是最终目标。我删除了我的帖子,请修改你的自我回答。我希望你不要删除你的答案。但是你确定它有效吗?在我的例子中,我无法让它工作-也许我只是用错了。天哪,老兄,确保它工作,:-)我肯定你在某个地方丢失了:-),我看不到自定义打印和自定义绘制之间的差异,从JTable plus Ta获取大小
// ...snip 

JOptionPane.showMessageDialog(null, p);

JFrame frame = new JFrame();
frame.setContentPane(p);
frame.pack();

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

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

JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
ImageIO.write(bi,"png",new File("table.png"));
    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();
   p.doLayout();
   p.setSize(p.getPreferredSize()) 
    //        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)));
    // strategy 1
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
    p.addNotify();

    // strategy 2
    scroll.setColumnHeaderView(table.getTableHeader());
    table.setPreferredScrollableViewportSize(table.getPreferredSize());
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"));
    }
}