将JPanel保存为图像高清质量 [英] Save JPanel as Image HD Quality

查看:333
本文介绍了将JPanel保存为图像高清质量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将JPanel保存为图像(Png,Jpg,无论如何),但使用Graphics2D,质量非常低。我的JPanel主要包含文本,我想在A4纸张尺寸上打印面板4次,以便填充页面。
但是当我打印图像时,文字就像褪色一样。我试图创建一个A3图像,然后将其打印到较小的A4尺寸。质量增加很少,几乎没有什么意义。

I am trying to save a JPanel as Image (Png, Jpg, whatever) but with Graphics2D the Quality is very low. My JPanel contains mostly text and I want to print the panel 4 times on a A4 paper size, so that it fills the page. But the text is like washed-out when i print the image. I tried to create an A3 image then print it to the smaller A4 size. The quality increases very little, almost insignificantly.

这是我用来生成图像的函数,基于这个ScreenImage.Class我发现这里

Here is the function i use to generate the image, based on this ScreenImage.Class i found here :

public void exportToPNG(JRootPane panel){
    Dimension size = panel.getSize();
    BufferedImage image = new BufferedImage(
            size.width, size.height * 4 /* use the same image 4 times */
            , BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = image.createGraphics();

    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
    g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
    g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
    g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
    g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

    g2.drawImage(ScreenImage.createImage(panel), 0, 0, size.width, size.height, null);
    g2.drawImage(ScreenImage.createImage(panel), 0, size.height, size.width, size.height, null);
    g2.drawImage(ScreenImage.createImage(panel), 0, size.height * 2, size.width, size.height, null);
    g2.drawImage(ScreenImage.createImage(panel), 0, size.height * 3, size.width, size.height, null);


    try{
        ImageIO.write(image, "png", new File("D:\\test-image.png"));

    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
}

以下是我生成的示例图片:
点击链接。

Here is a sample image i generated: click the link..

即使放大一点,你也应该看到图像上的褪色效果。

You should see that washed-out effect on the image even when zooming-in a little.

有没有办法提高质量?还是专用的图书馆?

Is there a way to increase the quality? or a dedicated library?

推荐答案

让我们从显而易见的开始......

Let's start with the obvious...


  • A4纸是21.0厘米x 29.7厘米。

  • 在300dpi时,这使得它成为2480.315x3507.874像素

  • 在72dpi,这使它成为595.2756x841.8898像素

为什么这很重要? Java以72dpi渲染到屏幕,但能够以300dpi(上下都打印,但这是个不错的数字)。这意味着,粗略地说,您需要将屏幕图像缩放4倍。向上扩展永远不会令人愉快,如此处

Why's this important? Java renders to the screen at 72dpi, but is capable of printing at 300dpi (above and below, but this is nice figure). This means, roughly, you'd to scale the screen image UP by 4 times. Up scaling is never pleasant, as demonstrated here

更好的解决方案是使用打印机DPI并将图像缩小到屏幕。

A better solution would be work with the printer DPI and scale the image down to the screen.

为方便起见,你可以使用类似的东西......

For convenience sake, you can use something like...

public static final float CM_PER_INCH = 0.393700787f;

public static float cmsToPixel(float cms, float dpi) {
    return cmToInches(cms) * dpi;
}

public static float cmToInches(float cms) {
    return cms * CM_PER_INCH;
}

要从给定DPI的厘米转换为像素。

To convert from cm's to pixels at a given DPI.

现在到了有趣的部分。您可以使用Swing组件来呈现基本布局,它可能更容易,但您必须缩小图形,因为核心打印机API假设DPI为72(不要问)。现在按比例缩小通常会产生更好的输出,但还有另一种解决方案。

Now to the fun part. You "could" use Swing components to render the basic layout, it might be easier, but you'd have to scale the graphics down, as the core printer API assumes a DPI of 72 (don't ask). Now scaling down generally results in a better output, but there is another solution.

相反,您可以使用Graphics 2D API并自己生成输出......

Instead, you could use the Graphics 2D API and generate the output yourself...

public static class Ticket {

    public enum TextAlignment {

        LEFT,
        RIGHT,
        CENTRE
    }

    protected static final int STUB_NUMBER_Y_POS = 12;

    private Font plainFont;
    private Font boldFont;

    private Stroke dashedStroke;

    public void paint(Graphics2D g2d, double pageWidth, double pageHeight, int stubNumber) {
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);

        paintLeftStub((Graphics2D) g2d.create(), pageWidth, pageHeight, stubNumber);
        paintBody((Graphics2D) g2d.create(), pageWidth, pageHeight, stubNumber);
        paintRightStub((Graphics2D) g2d.create(), pageWidth, pageHeight, stubNumber);
        paintEndStub((Graphics2D) g2d.create(), pageWidth, pageHeight, stubNumber);

        g2d = (Graphics2D) g2d.create();
        g2d.setColor(Color.GRAY);
        g2d.setStroke(getDashedStroke());
        g2d.draw(new Line2D.Double(0, pageHeight - 1, pageWidth, pageHeight - 1));
        g2d.dispose();

    }

    protected void paintLeftStub(Graphics2D graphics, double pageWidth, double pageHeight, int stubNumber) {

        graphics.setColor(Color.BLACK);
        double stubWidth = pageWidth / 4;

        Graphics2D g2d = (Graphics2D) graphics.create();

        Font font = getBoldFont().deriveFont(18f);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();

        // Did mention I hate doing inline transformations :P
        g2d.rotate(Math.toRadians(-90), stubWidth / 2, pageHeight / 2);
        g2d.translate(0, -((stubWidth - pageHeight) / 2));

        String lines[] = {"MORATUFIESTA", "", "Sat. 3 Auguest 2015", "Adult - $3"};
        double x = 2;
        double y = 0;
        double maxWidth = 0;
        for (String text : lines) {

            x = calculateHorizontalCenterPositionFor(text, fm, stubWidth);
            maxWidth = Math.max(maxWidth, fm.stringWidth(text));
            g2d.drawString(text, (int) Math.round(x), (int) Math.round(y + fm.getAscent()));
            y += fm.getHeight();

        }
        double blockWidth = y;

        // Easier then trying to undo the transformation...
        g2d.dispose();
        g2d = (Graphics2D) graphics.create();

        String text = "Low";

        font = getPlainFont().deriveFont(6f);
        g2d.setFont(font);
        fm = g2d.getFontMetrics();
        double xPos = calculateHorizontalCenterPositionFor(text, fm, blockWidth) + 2;
        double yPos = (pageHeight - maxWidth) / 2;
        g2d.drawString(text, (int) Math.round(xPos), (int) Math.round(yPos - fm.getAscent()));
        g2d.setStroke(getDashedStroke());
        g2d.draw(new Line2D.Double(stubWidth, 0, stubWidth, pageHeight));
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        drawStubNumber(g2d, stubWidth - 8 - fm.getHeight() - fm.getAscent(), STUB_NUMBER_Y_POS, stubNumber);
        g2d.dispose();

    }

    protected Stroke getDashedStroke() {

        if (dashedStroke == null) {

            float dash[] = {10.0f};
            dashedStroke = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 10f, dash, 0.0f);

        }

        return dashedStroke;

    }

    public Font getPlainFont() {

        if (plainFont == null) {

            plainFont = UIManager.getFont("Label.font");

        }

        return plainFont;

    }

    public Font getBoldFont() {

        if (boldFont == null) {

            boldFont = getPlainFont();
            boldFont = boldFont.deriveFont(Font.BOLD);

        }

        return boldFont;

    }

    protected double calculateHorizontalCenterPositionFor(String text, FontMetrics fm, double width) {
        return (width - fm.stringWidth(text)) / 2d;
    }

    protected void paintBody(Graphics2D graphics, double pageWidth, double pageHeight, int stubNumber) {

        int padding = 8;
        double xOffset = pageWidth / 4d;

        graphics.setColor(Color.BLACK);

        double bodyWidth = (pageWidth / 2d);
        Graphics2D g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        g2d.setFont(getPlainFont().deriveFont(12f));
        FontMetrics fm = g2d.getFontMetrics();
        String text = "Moratu Fiesta";
        double xPos = bodyWidth - fm.stringWidth(text) - padding;
        double yPos = padding;

        g2d.drawString(text, (int) Math.round(xPos), (int) Math.round(yPos + fm.getAscent()));
        g2d.dispose();

        Font plainFont = getPlainFont().deriveFont(9.5f);
        TextLine[] addressLines01 = new TextLine[]{
            new TextLine("61 Railway Pde North", plainFont),
            new TextLine("Glen Waverley", plainFont),
            new TextLine("03 9836 8673", plainFont)
        };
        TextLine[] addressLines02 = new TextLine[]{
            new TextLine("1120, Glen Huntly", plainFont),
            new TextLine("Glen Huntly", plainFont),
            new TextLine("03 9571 5544", plainFont)
        };
        TextLine[] sponsorLines = new TextLine[]{
            new TextLine("Proudly supported by", plainFont),
            new TextLine("Quality Groceries", plainFont.deriveFont(Font.BOLD)),
            new TextLine("Visit for all your grocery needs", plainFont)
        };

        Area area = new Area();
        addTo(g2d, area, addressLines01);
        addTo(g2d, area, addressLines02);
        addTo(g2d, area, sponsorLines);
        int height = area.getBounds().height;
        double bottomBlockYPos = pageHeight - height - padding;

        g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        drawTextLines(g2d, padding, bottomBlockYPos, bodyWidth - (padding * 2), TextAlignment.LEFT, addressLines01);
        drawTextLines(g2d, padding, bottomBlockYPos, bodyWidth - (padding * 2), TextAlignment.CENTRE, sponsorLines);
        drawTextLines(g2d, padding, bottomBlockYPos, bodyWidth - (padding * 2), TextAlignment.RIGHT, addressLines02);
        g2d.dispose();

        plainFont = getPlainFont().deriveFont(10f);
        TextLine[] textLines = new TextLine[]{
            new TextLine("On Saturday, August 3, 2013 from 6.30pm till midnight", plainFont.deriveFont(Font.BOLD)),
            new TextLine("At 21, Sacred Heart Parish Hall, Johnson Street, Oakleigh", plainFont)
        };
        int blockHeight = getSizeFor(g2d, textLines).height;
        double mainBlockYPos = (pageHeight - blockHeight) / 2;

        g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        drawTextLines(g2d, 0, mainBlockYPos, bodyWidth, TextAlignment.CENTRE, textLines);
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        Font boldFont = getBoldFont().deriveFont(9f);
        double upperYPos = (mainBlockYPos + blockHeight);
        double middleBlockYPos = upperYPos + ((bottomBlockYPos - upperYPos) / 2) - (g2d.getFontMetrics(boldFont).getHeight() / 2);
        drawTextLines(g2d, padding, middleBlockYPos, bodyWidth - (padding * 2), TextAlignment.LEFT, new TextLine("Melway Ref, 69 FB", boldFont));
        drawTextLines(g2d, padding, middleBlockYPos, bodyWidth - (padding * 2), TextAlignment.CENTRE, new TextLine("Music by REDEMPTION", boldFont));
        drawTextLines(g2d, padding, middleBlockYPos, bodyWidth - (padding * 2), TextAlignment.RIGHT, new TextLine("Donations $30", boldFont));
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        g2d.setStroke(getDashedStroke());
        g2d.draw(new Line2D.Double(bodyWidth, 0, bodyWidth, pageHeight));
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        drawStubNumber(g2d, padding + xOffset, STUB_NUMBER_Y_POS, stubNumber);
        g2d.dispose();

    }

    protected void drawStubNumber(Graphics2D g2d, double x, double y, int stubNumber) {

        Font font = getBoldFont().deriveFont(18f);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();

        String text = Integer.toString(stubNumber);

        g2d.translate(x, y);
        g2d.rotate(Math.toRadians(-90), fm.stringWidth(text) / 2, fm.getHeight() / 2);

        g2d.drawString(text, 0, fm.getAscent());
        g2d.dispose();
    }

    protected void paintRightStub(Graphics2D graphics, double pageWidth, double pageHeight, int stubNumber) {

        graphics.setColor(Color.BLACK);

        int padding = 8;
        double xOffset = (pageWidth / 4d) * 3;
        double stubWidth = (pageWidth / 4d) / 2;

        Graphics2D g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        g2d.setStroke(getDashedStroke());
        g2d.draw(new Line2D.Double(stubWidth, 0, stubWidth, pageHeight));
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        drawStubNumber(g2d, padding + xOffset, STUB_NUMBER_Y_POS, stubNumber);
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        String text = "Cafe Little Hut";
        Font font = getPlainFont().deriveFont(23f);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();

        double x = xOffset + ((stubWidth - fm.stringWidth(text)) / 2d);
        double y = ((pageHeight - fm.getHeight()) / 2d);

        g2d.translate(x, y);
        g2d.rotate(Math.toRadians(-90), fm.stringWidth(text) / 2, fm.getHeight() / 2);

        g2d.drawString(text, 0, fm.getAscent());

        g2d.dispose();

    }

    protected void paintEndStub(Graphics2D graphics, double pageWidth, double pageHeight, int stubNumber) {

        graphics.setColor(Color.BLACK);

        int padding = 8;
        double stubWidth = (pageWidth / 4d) / 2;
        double xOffset = ((pageWidth / 4d) * 3 + stubWidth);

        Graphics2D g2d = (Graphics2D) graphics.create();
        g2d.translate(xOffset, 0);
        g2d.setStroke(getDashedStroke());
        g2d.draw(new Line2D.Double(stubWidth, 0, stubWidth, pageHeight));
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        drawStubNumber(g2d, padding + xOffset, STUB_NUMBER_Y_POS, stubNumber);
        g2d.dispose();

        g2d = (Graphics2D) graphics.create();
        String text = "Entrance";
        Font font = getBoldFont().deriveFont(32f);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();

        double x = xOffset + ((stubWidth - fm.stringWidth(text)) / 2);
        double y = ((pageHeight - fm.getHeight()) / 2);

        g2d.translate(x, y);
        g2d.rotate(Math.toRadians(-90), fm.stringWidth(text) / 2, fm.getHeight() / 2);

        g2d.drawString(text, 0, fm.getAscent());

        g2d.dispose();

    }

    protected Dimension drawTextLines(Graphics2D g2d, double xPos, double yPos, double width, TextAlignment textAlignment, TextLine... textLines) {

        Area area = new Area();

        for (TextLine textLine : textLines) {
            g2d.translate(xPos, yPos);
            Dimension size = textLine.getBounds(g2d);
            textLine.paint(g2d, width, textAlignment);
            area.add(new Area(new Rectangle2D.Double(xPos, yPos, size.width, size.height)));
            g2d.translate(-xPos, -yPos);
            yPos += size.height;
        }

        return area.getBounds().getSize();

    }

    protected void addTo(Graphics2D g2d, Area area, TextLine... textLines) {

        area.add(new Area(new Rectangle(getSizeFor(g2d, textLines))));

    }

    protected Dimension getSizeFor(Graphics2D g2d, TextLine... textLines) {

        int yPos = 0;
        int width = 0;
        for (TextLine textLine : textLines) {
            Dimension size = textLine.getBounds(g2d);
            yPos += size.height;
            width = Math.max(size.width, width);
        }

        return new Dimension(width, yPos);

    }

    protected class TextLine {

        private String text;
        private Font font;

        public TextLine(String text, Font font) {
            this.text = text;
            this.font = font;
        }

        public String getText() {
            return text;
        }

        public Font getFont() {
            return font;
        }

        public Dimension getBounds(Graphics2D g2d) {
            FontMetrics fm = g2d.getFontMetrics(getFont());
            return new Dimension(fm.stringWidth(text), fm.getHeight());
        }

        public void paint(Graphics2D g2d, double width, TextAlignment textAlignment) {
            Dimension bounds = getBounds(g2d);
            FontMetrics fm = g2d.getFontMetrics(getFont());
            g2d.setFont(font);
            double x = 0;
            switch (textAlignment) {
                case CENTRE:
                    x = (width - bounds.width) / 2;
                    break;
                case RIGHT:
                    x = width - bounds.width;
                    break;
            }
            g2d.drawString(getText(), (int) Math.round(x), fm.getAscent());
        }

    }

}

你为什么这样做?包装 Printable 更容易打印到打印机,你也可以绘制到组件(或图像)

Why would you do that? It's easier to wrap a Printable around and print to a printer and you can also "paint" to a component (or image)

例如......

public class TicketPrintable implements Printable {

    private Ticket ticket;

    public TicketPrintable(Ticket ticket) {
        this.ticket = ticket;
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        int result = NO_SUCH_PAGE;
        if (pageIndex == 0) {
            Graphics2D g2d = (Graphics2D) graphics;
            double width = pageFormat.getImageableWidth();
            double height = pageFormat.getImageableHeight();

            g2d.translate((int) pageFormat.getImageableX(),
                            (int) pageFormat.getImageableY());

            double ticketHeight = height / 4d;
            for (int index = 0; index < 4; index++) {

                ticket.paint(g2d, width, ticketHeight, index + 1);
                g2d.translate(0, ticketHeight);

            }

            result = PAGE_EXISTS;
        }
        return result;
    }

}

要打印它,你会使用像...这样的东西。

And to print it, you would use something like...

PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
aset.add(new MediaPrintableArea(0, 0, 210, 297, MediaPrintableArea.MM));

PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new TicketPrintable(new Ticket()));

if (pj.printDialog(aset)) {
    try {
        pj.print(aset);
    } catch (PrinterException ex) {
        ex.printStackTrace();
    }
}

在屏幕上看起来像......

On the screen it looks like...

在纸面上它看起来像(缩小为SO)

On paper it looks like (scaled down for SO)

现在我已经说过了,我强烈建议你学习JasperReports,这使得这一切变得简单......

Now having said that, I would strongly encourage you to learn JasperReports, which makes this all so much simpler...

已更新

所以,我坐在交通中并想到自己,我想知道是否我可以使用缩放将 Ticket 呈现给图像,所以我想我试试看......

So, I was sitting in traffic and thought to myself, I wonder if I can just use scaling to render the Ticket to an image, so I thought I'd give it a try...

顶部图像为72dpi,底部图像缩放为300dpi

The top image is 72dpi, the bottom image is scaled to 300dpi

double pageWidth = cmsToPixel(21.0f, 300f);
double pageHeight = cmsToPixel(29.7f, 300f);
double imageWidth = cmsToPixel(21.0f, 72f);
double imageHeight = cmsToPixel(29.7f, 72f);

double scaleFactor = ImageUtilities.getScaleFactorToFit(
        new Dimension((int) Math.round(imageWidth), (int) Math.round(imageHeight)),
        new Dimension((int) Math.round(pageWidth), (int) Math.round(pageHeight)));

int width = (int) Math.round(pageWidth);
int height = (int) Math.round(pageHeight);

BufferedImage img = new BufferedImage(
        width,
        height,
        BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fill(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
g2d.scale(scaleFactor, scaleFactor);

Ticket ticket = new Ticket();
ticket.paint(g2d, img.getWidth() / scaleFactor, (img.getHeight() / scaleFactor) / 4, 1);
g2d.dispose();

try {
    ImageIO.write(img, "png", new File("Ticket.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}

比例因子算法

public static double getScaleFactorToFit(Dimension original, Dimension toFit) {

    double dScale = 1d;

    if (original != null && toFit != null) {

        double dScaleWidth = getScaleFactor(original.width, toFit.width);
        double dScaleHeight = getScaleFactor(original.height, toFit.height);

        dScale = Math.min(dScaleHeight, dScaleWidth);

    }

    return dScale;

}


public static double getScaleFactor(int iMasterSize, int iTargetSize) {

    double dScale = 1;
    if (iMasterSize > iTargetSize) {

        dScale = (double) iTargetSize / (double) iMasterSize;

    } else {

        dScale = (double) iTargetSize / (double) iMasterSize;

    }

    return dScale;

}

注意:这只是真正适用于文本和原始图形,你把图像放入这个,它将无法工作,图像将按比例放大,看起来很糟糕,使用前面的链接答案演示。在这种情况下,您必须将表单设计为以300 + dpi渲染并将图像缩小到72dpi

Note: This is only really going to work for text and primitive graphics, you put an image into this and it won't work, the image will be scaled up and look crappy, use demonstrated in the linked answer from before. In that case, you'd have to design the form to render at 300+dpi and scale the image down to 72dpi

这篇关于将JPanel保存为图像高清质量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆