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

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

问题描述

我提供了关于在类并包含对 doLayout(组件)的调用)方法。如果从未在屏幕上实现 Component ,则此方法很有用,但对此代码没有任何影响(在尝试之前,会弹出包含选项窗格中的表的面板渲染它)。



为了让表格标题呈现需要什么?



更新1



更改行..

  p.paint(g); 

..到(有适当的导入)..

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

..生产..



< img src =https://i.stack.imgur.com/OxOy2.pngalt =第二次尝试>



我会继续调整它。



更新2



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



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



虽然策略1可能更进一步调整以解决这个问题,我真的很喜欢策略2的简洁,所以它得到了剔除。



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



更新3



这是由提出的方法生成的图像由camickr和kleopatra。我已经把它放了两次,但在我看来,它们是相同的(虽然我没有按像素比较进行)。



  import javax 。摇摆。*; 
import java.awt。*;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import java.io.File;

class TableImage {

String [] columns = {Name,Age,GPA,Pass};
/ **与生者或死者有任何相似之处纯粹是偶然的。 * /
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);

返回表;
}

/ **方法由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/ * /
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);
返回bi;
}

/ **方法由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);

//未显示,假冒全部预付
p.addNotify();

//手动调整大小为pref
p.setSize(p.getPreferredSize());

//验证强制递归doLayout的孩子
p.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表;
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。

解决方案


这个线程并不要求在没有首先显示它的情况下渲染表,但这是最终目标


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代码只会为不可显示的组件布置组件。我可能会考虑让这更通用。


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天全站免登陆