调整 JComponent 的大小以进行文件导出

发布于 2024-08-21 08:14:42 字数 2167 浏览 11 评论 0原文

我有一个 JPanel,在上面使用通常的“paintComponent(Graphics g)”方法绘制了许多自定义编写的 JComponent。我使用 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();
    }
}

如何“绘制”适合导出的图像,但实际上不会显示该新图像?

谢谢!


好吧,我又回到这个问题了......

我正在绘制的场景包含一些文本,现在最终用户希望以“肖像”长宽比导出图形。由于我不是在新的维度中重新绘制场景,而只是缩放图像,这会导致文本在水平方向上被严重挤压。

无论如何?

I have a JPanel upon which I draw a number of custom-written JComponents using the usual 'paintComponent(Graphics g)' method. I use a JLayeredPane to control the display order of the custom components, as follows:

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

Now, I would like to export this panel to a JPEG file, but with a different size. When I use the following code, it successfully creates/exports a JPEG file of the desired size, but it also updates my screen image version of the panel to the new size! Yikes!

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();
    }
}

How can I 'draw' an image suitable for exporting, but not actually cause this new image to be displayed?

Thanks!


Well, I'm back to this problem again.....

The scene I'm painting includes some text and now the end user wants the graph exported in a 'portrait' aspect ratio. Since I'm not repainting the scene in the new dimensions but just scaling the image, this causes the text to be seriously squashed horizontally.

Anyway around that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

GRAY°灰色天空 2024-08-28 08:14:42

看起来是第二个优秀的解决方案。我的最终解决方案如下所示:

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();
    }
}

Looks like a second excellent solution. The final solution I have looks like the following:

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();
    }
}
纸短情长 2024-08-28 08:14:42

根本不要调整面板的大小;只需创建一个 BufferedImage 这是面板的当前大小并绘制它。获得快照后,立即将其缩放到所需的尺寸 BufferedImage 使用 drawImage ()AffineTransformOp

附录: AffineTransformOp< 的一个优点/code>是对旋转、插值、缩放和纵横比的控制:

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

Don't resize your panel at all; just create a BufferedImage that's the panel's current size and paint it. Once you've got the snapshot, scale it to your desired dimensions in a second BufferedImage using drawImage() or AffineTransformOp.

Addendum: One advantage of AffineTransformOp is control over rotation, interpolation, scale and aspect ratio:

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);
笔芯 2024-08-28 08:14:42

好吧,让一切看起来都正常的唯一方法(例如,在光栅化后不缩放文本)是使用新尺寸在新图形上下文上绘制图像。这是我的新“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()”方法,将它们绘制到新的缓冲图像上。有点工作,但结果正是我需要的。

Well, the only way I could get everything to look OK (e.g., no scaling of text after it's been rasterized) is to draw the image on a new graphics context using the new size. Here's my new 'export()' method.

    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();
    }
}

The 'draw()' method called above calls the 'setbounds()' method on all of my sub-components which draws them onto the new buffered image. A bit of work, but the result is exactly what I need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文