4

JScrollPane (画面より大きい) のメイン ビューポートとヘッダーを PNG 画像ファイルに保存しようとしています。JPanel を拡張する 3 つのクラス (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);
    }

外部 JFrame から、次のコードを使用して PNG ファイルに保存しようとしました。

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

これは、実行中のアプリケーションのスクリーンショットです:スクリーンショット

そして、これはエクスポートされたヘッダーです:

「super.paint(g)」命令にコメントすると、正しい画像が得られます (したがって、すべての JLables がなくても明らかです)。2 番目のペイント (super.paint(g)) が BufferedImage にシフトされてペイントされ、その JPanel の外側に要素が取り込まれているようです。誰かが私にこの振る舞いを説明できますか? ありがとうございました。

========== SSCCE の編集 ===================================

これはコンパイルする必要があります。そのまま実行すると、c:\ に 2 つのヘッダーと同じはずの 2 つの画像 (top.png と left.png) が見つかります。残念ながら、そうではありません。背景は未塗装です。さらに (特に left.png を見ると)、ラベルが 2 回ペイントされ、シフトされていることがわかります (たとえば、「Left test 21」に注意してください)。

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

1 に答える 1

0

異常な動作を再現することはできませんでしたが、期待に合わせてイメージ ペイントの原点 (g.translate()) をシフトするのを忘れていたと推測されます。また、安全のため、画像タイプは ARGB を使用しないでください。イメージ タイプ RGB を使用します。特定の Java 実装が原因である可能性は十分にあります。実装は、サブコンポーネントのペイントを 1 回だけ呼び出すという契約はありません。

于 2012-12-14T23:02:18.200 に答える