0

I have a funny problem trying to export custom Java JPanels to a PNG file. The export process of the components I've been writing up until now have worked flawlessly.

My JPanels include custom-written JComponents (e.g., override paintComponent(Graphics g) and write what I have to).

The export process looks like the following (of the extended JPanel I have):

 public void export(File file, int width, int height)
  throws IOException
{
     Dimension size = getSize();

     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
     Graphics2D g2 = image.createGraphics();
     draw (g2, new Rectangle (0, 0, width, height));

     try {
         ImageIO.write(image, "png", file);
     } catch (FileNotFoundException e) {
         throw new IOException ("Unable to export chart to ("
               + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
     } finally {
         g2.dispose();
     }
}

The 'draw()' method above causes all of the JPanel's child components to be re-drawn using the new size of the image to be exported. Works very well.

The problem I have today is that I have one custom JPanel that includes some Swing components (a JScrollPane wrapping a JEditorPane). This JPanel includes one of my custom JComponents and then this second JComponent with the JScrollPane on it.

About 75% of the time, this second JComponent with the JScrollPane is not positioned correctly in the exported image when I perform the export. It is positioned at Point (0, 0) and the size is what it looks like on the screen. The 'draw()' method for this JComponent looks like the following:

public void draw(Graphics2D g2, Rectangle componentArea) {

    scrollPane.setBounds(componentArea);
    textArea.setText(null);
    sb.append("<html>");
    sb.append("<h1 style=\"text-align:center;\">" + "XXXXXXXXX  XXXXXXX" + "</h1>");
    textArea.setText(sb.toString());

    super.paintComponents(g2);
}

But about 25% of the time this works - this JComponent with the scrollpane is correctly positioned in my exported image. The re-draw the componment works.

It is like there is some double-buffering going on here that I can't figger out....

Ideas?

4

4 に答える 4

0

paintComponents() ではなく、paint() メソッドを呼び出してみます。

おそらく、エディター ペインのテキストを設定しているために、テキストが適切に解析されておらず、コンポーネントを描画しようとしたときにドキュメントが最終状態になっていない可能性があります。または、コンポーネントの境界を動的に設定しているため、問題が発生している可能性があります。super.paint() メソッドを SwingUtilities.invokeLater() でラップしてみてください。

ScreenImageクラスは、画像の作成に使用するクラスです。しかし、私は常に静的 GUI のイメージを作成するためにそれを使用してきました。つまり、イメージを作成すると同時にコンポーネントの境界を変更しません。

于 2010-08-27T02:42:15.630 に答える
0

解決策を発見!! 「塗装イベントのスケジュール」に関するあなたのコメントは、私の頭の中で少し鳴り響きました。私は数年前にこのような問題を抱えていて、それを忘れていました。老後はそうなる……。

解決策は、「draw()」メソッドを「SwingUtilities.invokeAndWait()」でラップすることです。出来上がり!私の 'export()' メソッドは次のようになります。

    public void export(File file, final int width, final int height)
    throws IOException
{

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    final Graphics2D g2 = image.createGraphics();

    //  Must wait for the bloody image to be drawn as Swing 'paint()' methods
    //  merely schedule painting events.  The 'draw()' below may not complete
    //  the painting process before the 'write()' of the image is performed.

    //  thus, we wait....

    try {
        SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                draw (g2, new Rectangle (0, 0, width, height));
            }
        });
        ImageIO.write(image, "png", file);
    } catch (FileNotFoundException e) {
        throw new IOException ("Unable to export chart to ("
                + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } catch (InterruptedException e) {
        e.printStackTrace();
        throw new IOException ("Unable to export chart to ("
                + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } catch (InvocationTargetException e) {
        e.printStackTrace();
        throw new IOException ("Unable to export chart to ("
                + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } finally {
        g2.dispose();
    }
}

うわー!

于 2010-08-27T17:03:42.653 に答える
0

Swing コンポーネントのレイアウトは通常、すぐにではなく遅延して発生するため、断続的な動作が発生する可能性があります。scrollPane.doLayout() を直接呼び出してみることもできます。通常、これは悪い考えですが、ペイントする前に scrollPane がレイアウトされることを保証する必要があります。

また、画面外の画像にペイントする場合は、おそらく、paintComponents(g) ではなく printAll(g) を呼び出す必要があります。これにより、ダブル バッファリングの問題が回避されます。

于 2010-08-27T09:14:06.697 に答える
0

カスタム コンポーネントで提供された Graphics オブジェクトの Transform オブジェクトを何らかの変更で変更しますか? 最初に必ず保存してから、目的に合わせて新しいインスタンスを変更し、完了したら、古い変換を元に戻してください。

于 2010-08-26T21:28:09.430 に答える