为什么 JTable 标题没有出现在图像中? [英] Why does the JTable header not appear in the image?

查看:33
本文介绍了为什么 JTable 标题没有出现在图像中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 类并包含调用 doLayout(Component) 方法.如果 Component 从未在屏幕上实现,但对该代码没有影响(在尝试渲染它之前,它会在选项窗格中弹出包含表格的面板),该方法很有用.>

需要什么才能呈现表头?

更新 1

换行..

 p.paint(g);

..to(具有适当的导入)..

 p.paint(g);JTableHeader h = table.getTableHeader();h.油漆(g);

..产生..

我会继续调整它.

更新 2

kleopatra(策略 1)&camickr(策略 2)都提供了一个答案,两者都有效,&两者都不需要将 JTable 添加到虚拟组件(这是一个巨大的黑客 IMO).

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

虽然可能会进一步调整策略 1 以解决这个问题,我真的很喜欢策略 2 的简洁性,所以它得到了勾选.

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

更新 3

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

import javax.swing.*;导入 java.awt.*;导入 java.awt.image.BufferedImage;导入 javax.imageio.ImageIO;导入 java.io.File;类表图像{String[] columns = {姓名"、年龄"、GPA"、通过"};/** 与生者或死者的任何相似之处纯属偶然.*/对象[][] 数据 = {{André", new Integer(23), new Double(47.64), new Boolean(false)},{珍妮",新整数(23),新双(84.81),新布尔(真)},{罗伯托",新整数(22),新双精度(78.23),新布尔(真)}};表图像(){}公共 JTable getTable() {JTable table = new JTable(data, columns);table.setGridColor(新颜色(115,52,158));table.setRowMargin(5);table.setShowGrid(true);返回表;}/** 方法由 camickr 提供.https://stackoverflow.com/questions/7369814/why-does-the-jtable-header-not-appear-in-the-image/7375655#7375655需要 ScreenImage 类可从..http://tips4java.wordpress.com/2008/10/13/screen-image/*/公共 BufferedImage getImage1(JTable 表){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);返回bi;}/** 方法由 kleopatra 提供.https://stackoverflow.com/questions/7369814/why-does-the-jtable-header-not-appear-in-the-image/7372045#7372045 */公共 BufferedImage getImage2(JTable 表){JScrollPane scroll = new JScrollPane(table);table.setPreferredScrollableViewportSize(table.getPreferredSize());JPanel p = new JPanel(new BorderLayout());p.add(scroll, BorderLayout.CENTER);//没有被显示,假装准备好了p.addNotify();//手动调整大小p.setSize(p.getPreferredSize());//验证以强制子项的递归 doLayoutp.validate();BufferedImage bi = new BufferedImage(p.getWidth(), p.getHeight(), BufferedImage.TYPE_INT_RGB);图形 g = bi.createGraphics();p.paint(g);g.dispose();返回bi;}public void writeImage(BufferedImage image, String name) 抛出异常 {ImageIO.write(image,"png",new File(name + ".png"));}public static void main(String[] args) 抛出异常 {UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");TableImage ti = new TableImage();JTable 表;缓冲图像双;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.

解决方案

该线程不要求在不首先显示的情况下渲染表格,但这是最终目标

ScreenImage 处理这个.

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

import javax.swing.*;导入 java.awt.Graphics;导入 java.awt.BorderLayout;导入 java.awt.image.BufferedImage;导入 javax.imageio.ImageIO;导入 java.io.File;类表图像{public static void main(String[] args) 抛出异常 {对象[][] 数据 = {{"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 代码只会为不可显示的组件布置组件.我可能会考虑使这更通用.

I was offering advice on capturing an image of tabular data on Java API or Tool to convert tabular data into PNG image file - when the OP requested a code sample. Turns out to be harder than I thought! The JTable header vanishes from the PNG that the code writes.

PNG

Screen shot

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

Note: I checked over camickr's Screen Image class and included a call to the doLayout(Component) method. The method is useful for if a Component has never been realized on screen, but has no effect on this code (which pops the panel containing the table in an option pane before trying to render it).

What is needed in order to get the table header to render?

Update 1

Changing the line..

        p.paint(g);

..to (with an appropriate import)..

        p.paint(g);
        JTableHeader h = table.getTableHeader();
        h.paint(g);

..produces..

I'll keep tweaking it.

Update 2

kleopatra (strategy 1) & camickr (strategy 2) have provided an answer each, both of which work, & neither of which requires adding the JTable to a dummy component (which is an huge hack IMO).

While strategy 2 will crop (or expand) to 'just the table', the 1st strategy will capture the panel containing the table. This becomes problematic if the table contains many entries, showing an image of a truncated table with a scroll bar.

While strategy 1 might be further tweaked to get around that, I really like the neat simplicity of strategy 2, so it gets the tick.

As pointed out by kleopatra, there was no 'tweak' needed. So I'll try again..

Update 3

This is the image produced by the methods put forward by both camickr and kleopatra. I'd have put it twice, but to my eye, they are identical (though I have not done a pixel by pixel comparison).

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

Both achieve the goal. Using camickr's method you leverage the further power of the ScreenImage API. Using kleopatra's method - about a dozen lines (less the comments and white space) of pure J2SE.

While ScreenImage is a class I will use and recommend in future, the other approach using core J2SE is what I'd probably use for this exact circumstance.

So while the 'tick' will stay with camickr, the bounty is going to kleopatra.

解决方案

It was not a requirement of this thread to render the table without first displaying it, but that was the ultimate goal

ScreenImage handles this.

You must manually add the header to the scrollpane.

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

Note: Kleopatra's suggeston to use the addNotify() on the panel will not work with ScreenImage. The addNotify() method makes the component displayable and the ScreenImage code will only lay out the components for non-displayable components. I might look into making this more general.

这篇关于为什么 JTable 标题没有出现在图像中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆