1

通常の「paintComponent(Graphics g)」メソッドを使用して多数のカスタム作成 JComponents を描画する JPanel があります。次のように、JLayeredPane を使用して、カスタム コンポーネントの表示順序を制御します。

public Class MyPanel extends JPanel {
    private JLayeredPane layeredPane = new JLayeredPane();
    private JComponent component1;
    private JComponent component2;

    public MyPanel() {
        super();
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

        component1 = new CustomComponent1();
        layeredPane.add (component1, new Integer(0));

        component2 = new CustomComponent2();
        layeredPane.add (component2, new Integer(1));

        add (layeredPane);
    }

    public void resizePanel(Graphics g, int newWidth, int newHeight) {
        component1.setBounds (f(x), f(y), f(newWidth), f(newHeight));
        component2.setBounds (f(x), f(y), f(newWidth), f(newHeight));
    }

    public void paintComponent(Graphics g) {
        if ((getWidth() != oldWidth) || (getHeight() != oldHeight)) {
            oldWidth = getWidth();
            oldHeight = getHeight();
            resizePanel (g, getWidth(), getHeight());
        }
        super.paintComponent(g);
    }

ここで、このパネルを JPEG ファイルにエクスポートしたいと思いますが、サイズが異なります。次のコードを使用すると、目的のサイズの JPEG ファイルが正常に作成/エクスポートされますが、パネルの画面イメージ バージョンも新しいサイズに更新されます。うわぁ!

public void export(File file, int width, int height)
    throws IOException
{
    BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = scaledImage.createGraphics();
    resizePanel (g2, width, height);
    super.paintComponent (g2);

    try {
        OutputStream out = new FileOutputStream(file);
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        encoder.encode(scaledImage);
        out.close();
    } catch (FileNotFoundException e) {
        throw new IOException ("Unable to export chart to ("
                  + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } finally {
        g2.dispose();
    }
}

エクスポートに適した画像を「描画」できますが、実際にはこの新しい画像が表示されませんか?

ありがとう!


さて、またこの問題に戻ってきました……。

私が描いているシーンにはいくつかのテキストが含まれており、エンド ユーザーはグラフを「ポートレート」アスペクト比でエクスポートすることを望んでいます。シーンを新しい次元で再描画するのではなく、画像をスケーリングするだけなので、テキストが水平方向に大きく押しつぶされます。

とにかくそのあたり?

4

3 に答える 3

1

パネルのサイズをまったく変更しないでください。BufferedImageパネルの現在のサイズの を作成してペイントするだけです。スナップショットを取得したら、またはBufferedImageを使用してすぐに目的のサイズにスケーリングします。drawImage()AffineTransformOp

補遺: の利点の 1 つAffineTransformOpは、回転、補間、スケール、アスペクト比を制御できることです。

BufferedImage image = ...
int w = image.getWidth();
int h = image.getHeight();
AffineTransform scaleTransform = new AffineTransform();
// last-in-first-applied: rotate, scale
scaleTransform.scale(scaleX, scaleY);
scaleTransform.rotate(Math.PI / 2, w / 2, h / 2);
AffineTransformOp scaleOp = new AffineTransformOp(
        scaleTransform, AffineTransformOp.TYPE_BILINEAR);
BufferedImage new = scaleOp.filter(image, null);
于 2010-02-11T18:00:07.417 に答える
1

2番目の優れたソリューションのように見えます。私が持っている最終的な解決策は次のようになります。

public void export(File file, int width, int height)
throws IOException
{
    BufferedImage scaledImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = scaledImage.createGraphics();
    g2.scale(((double) width)/((double)getWidth()), ((double) height)/((double)getHeight()));
    paintComponents(g2);
    try {
        ImageIO.write(scaledImage, "jpg", file);            
    } catch (FileNotFoundException e) {
        throw new IOException ("Unable to export chart to ("
         + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } finally {
        g2.dispose();
    }
}
于 2010-02-11T19:20:46.333 に答える
0

すべてを適切に表示する唯一の方法 (たとえば、ラスタライズ後にテキストをスケーリングしない) は、新しいサイズを使用して新しいグラフィックス コンテキストで画像を描画することです。これが私の新しい「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 (Exception e) {
        throw new IOException ("Unable to export chart to ("
                + file.getAbsolutePath() + "): " + e.getLocalizedMessage());
    } finally {
        g2.dispose();
    }
}

上記で呼び出された「draw()」メソッドは、すべてのサブコンポーネントで「setbounds()」メソッドを呼び出し、それらを新しいバッファリングされた画像に描画します。ちょっとした作業ですが、結果はまさに私が必要としているものです。

于 2010-08-27T20:23:44.800 に答える