Java JScrollPane内容到图像

Java JScrollPane内容到图像,java,swing,jscrollpane,bufferedimage,columnheader,Java,Swing,Jscrollpane,Bufferedimage,Columnheader,我正在尝试将JScrollPane(大于屏幕)的主视口和标题保存为PNG图像文件。 我创建了3个扩展JPanel的类(MainTablePanel、MapsHeaderPanel和ItemsHeaderPanel),并将它们设置为视口。他们每个人都有这样的方法: public BufferedImage createImage() { BufferedImage bi = new BufferedImage(getSize().width, getSize().height, Buffe

我正在尝试将JScrollPane(大于屏幕)的主视口和标题保存为PNG图像文件。 我创建了3个扩展JPanel的类(MainTablePanel、MapsHeaderPanel和ItemsHeaderPanel),并将它们设置为视口。他们每个人都有这样的方法:

public BufferedImage createImage() {
    BufferedImage bi = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB); 
    Graphics g = bi.createGraphics();
    paint(g); 
    g.dispose();
    return bi;
}
每个类还有一个paint方法,该方法绘制背景,然后调用super.paint()来绘制一些标签。例如:

public void paint(Graphics g){
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(new Color(255, 255, 0, 50));
        // for loop that paints some vertical yellow lines
        for(int i=0; i<getWidth(); i+=K.mW){
            g.fillRect(i-1, 0, 2, getHeight());
            if(i%(K.mW*5)==0){
                g.fillRect(i-2, 0, 4, getHeight());
            }
        }
        // called to pain some rotated JLabels
        super.paint(g);
    }
这是正在运行的应用程序的屏幕截图:

这是导出的标题:

如果我对“super.paint(g)”指令进行注释,我会得到一个正确的图像(因此没有所有的JLables)。 看起来第二个绘制(super.paint(g))被绘制到BuffereImage中,并将元素带到其JPanel之外。有人能解释我的这种行为吗?多谢各位

==========为SSCCE编辑====================================

这应该可以编译。您可以按原样执行,在c:\中,您会发现两个图像(top.png和left.png)应该与这两个标题相同。不幸的是,事实并非如此。背景未绘制。此外(特别是如果您查看left.png),您可以看到标签被绘制两次并移动(例如,请注意,“left test 21”)

import java.awt.*;
导入java.awt.image.buffereImage;
导入java.io.File;
导入javax.imageio.imageio;
导入javax.swing.*;
公共班机{
公共静态void main(字符串[]args){
JFrame=新JFrame();
frame.setLayout(空);
框架设置尺寸(800600);
JScrollPane scrollP=新的JScrollPane();
scrollP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL\u SCROLLBAR\u ALWAYS);
scrollP.setHorizontalScrollBarPolicy(JScrollPane.HorizontalScrollBar\uAlways);
MyPanel top=新的MyPanel();

对于(int i=0;i我无法再现任何异常行为,但我猜您忘记移动图像绘制原点(g.translate())为了符合您的期望。另外,为了安全起见,不要使用图像类型ARGB。使用图像类型RGB。完全有可能是您的特定java实现造成的。实现没有合同只对子组件调用一次paint。

如果将
super.paint(g);
作为
paint()中的第一行调用该怎么办;
?@Nikolay Kuznetsov可能不会viewport@SebastianIkaros Rizzo这个问题没有答案,为了更好的帮助,请尽快发布一个简短的、可运行的、可编译的检查,以获取有关渲染组件的提示。@NikolayKuznetsov背景画在标签上,我得到的图像与根本不调用super.paint(g)的图像完全相同
BufferedImage tableImg = mainTableP.createImage();
BufferedImage topImg = mapsHeaderP.createImage();
BufferedImage leftImg = itemsHeaderP.createImage();

ImageIO.write(tableImg, "png", new File(s.homeDir+"/table.png"));
ImageIO.write(topImg, "png", new File(s.homeDir+"/top.png"));
ImageIO.write(leftImg, "png", new File(s.homeDir+"/left.png"));
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;

public class Main {

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        frame.setLayout(null);
        frame.setSize(800, 600);

        JScrollPane scrollP = new JScrollPane();
        scrollP.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollP.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);

        MyPanel top = new MyPanel();
        for(int i=0; i<30; i++){
            JLabel label = new JLabel("Test "+i);
            label.setOpaque(false);
            label.setBounds(50*i, 40, 50, 20);
            label.setForeground(Color.GREEN);
            top.add(label);
        }
        top.setLayout(null);
        top.setOpaque(false);
        top.setPreferredSize(new Dimension(50*30, 200));
        top.validate();

        MyPanel left = new MyPanel();
        for(int i=0; i<30; i++){
            JLabel label = new JLabel("Left test "+i);
            label.setBounds(0, 50*i, 100, 20);
            label.setForeground(Color.RED);
            left.add(label);
        }
        left.setLayout(null);
        left.setOpaque(false);
        left.setPreferredSize(new Dimension(200, 50*30));

        MyPanel center = new MyPanel();
        center.setLayout(null);
        center.setOpaque(false);
        center.setPreferredSize(new Dimension(50*30, 50*30));

        scrollP.setViewportView(center);
        scrollP.setColumnHeaderView(top);
        scrollP.setRowHeaderView(left);

        scrollP.setBounds(0, 50, 750, 500);
        frame.add(scrollP);

        frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);

        try{
            BufferedImage topImg = top.createImage();
            ImageIO.write(topImg, "png", new File("C:/top.png"));

            BufferedImage leftImg = left.createImage();
            ImageIO.write(leftImg, "png", new File("C:/left.png"));
        }catch(Exception e){
            e.printStackTrace();
        }
    }


}

class MyPanel extends JPanel{
    public void paint(Graphics g){
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(new Color(255, 255, 0, 50));
        for(int i=0; i<getWidth(); i+=50){
            g.fillRect(i-1, 0, 2, getHeight());
        }
        super.paint(g); // COMMENT this line to obtain background images
    }

    public BufferedImage createImage() {
        BufferedImage bi = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB); 
        Graphics g = bi.createGraphics();
        paint(g);
        g.dispose();
        return bi;
    }
}