【问题标题】:Create BufferedImage with unknown dimensions创建尺寸未知的 BufferedImage
【发布时间】:2014-11-17 12:27:04
【问题描述】:

我有一个扩展 BufferedImage 的类,它应该显示为提供给它的构造函数的字符串。我希望这样做的原因是允许graphics2D 的抗锯齿功能(有关更多详细信息,请参阅我的previous question,如果您有任何更好的建议,请务必提出建议!)。我现在可以使用BufferedImage 类,但是我无法弄清楚如何确定所需的宽度和高度,以便在实际设置字体之前显示输入字符串。一旦设置了初始大小,我也找不到调整 BufferedImage 父级大小的方法。这是我的代码:

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Test extends JFrame{
    public Test(){
        this.add(new JLabel(new ImageIcon(new IconImage("Test", new Font("Sans-Serif", Font.PLAIN, 16)))));
        this.setVisible(true);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.pack();
    }

    class IconImage extends BufferedImage{
        public IconImage(String text, Font font){
            super(..., ..., BufferedImage.TYPE_INT_ARGB);//*****Unknown dimensions*****

            Graphics2D g2d = (Graphics2D) this.getGraphics();
            g2d.setFont(font);
            g2d.setColor(Color.BLACK);

            int stringHeight = (int) g2d.getFontMetrics().getStringBounds(text, g2d).getHeight();  
            g2d.drawString(text, 0 , stringHeight);
            g2d.dispose();
        }
    }

    public static void main(String[] args){
        new Test(); 
    }
}

有什么建议吗?谢谢。

【问题讨论】:

  • 请问您为什么尝试先创建图像然后创建按钮?你有可能反过来做吗? (如果是:您可以测量按钮,然后创建该图像)顺便说一句:如何显示比您的组件更大的图形 - 它可以工作但被剪裁......
  • 因为实际实现只是创建一个按钮,然后调用setIconsetRolloverIcon。我无法弄清楚如何仅对调用了setText 的按钮执行抗锯齿。

标签: java swing fonts font-size bufferedimage


【解决方案1】:

两种可能的解决方案:

  1. 创建一个微小的 BufferedImage (1x1) 只是为了获取 Graphics 对象并进行计算。然后创建真实图像
  2. 创建任意尺寸的 BufferedImage 并将文本缩放到 BufferedImage 的大小。有关缩放的示例,请参阅StandardPrint.preview

【讨论】:

  • 第 1 点实际上是我自提出问题以来一直在研究的内容。它有效,虽然有点迟钝,所以我问了这个问题,看看是否真的有更传统的方法。
  • 我经常使用第一种策略。
  • @AndrewThompson 哦,好吧,那我就这么做吧。
【解决方案2】:

我只找到了相对间接的代码。 需要 FontMetrics,这取决于图形设备(屏幕/打印机)。

因此我制作了一个与屏幕兼容的超大图像。

static BufferedImage textToImage(Font font, String text) {
    BufferedImage testImg = GraphicsEnvironment.getLocalGraphicsEnvironment()
            .getDefaultScreenDevice()
            .getDefaultConfiguration()
            .createCompatibleImage(1000, 100);
    FontMetrics fm;

    Graphics2D g = testImg.createGraphics();
    g.setFont(font);
    fm = g.getFontMetrics(font);
    Rectangle2D bounds = fm.getStringBounds(text, g);
    System.out.println("Bounds: " + bounds);
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, testImg.getWidth(), testImg.getHeight());
    g.setColor(Color.MAGENTA.darker());
    g.drawString(text, 0, fm.getHeight() - fm.getDescent());
    g.dispose();

    Rectangle viewR = new Rectangle(0, 0, 1000, 100);
    Rectangle iconR = new Rectangle();
    Rectangle textR = new Rectangle();
    String displayedText = SwingUtilities.layoutCompoundLabel(fm, text, null,
                     SwingConstants.TOP, SwingConstants.LEFT, 0, 0,
                     viewR, iconR, textR, 0);

    System.out.println("textR: " + textR);
    BufferedImage img = testImg.getSubimage(0, 0, textR.width, textR.height);
    return img;
}

字符串边界是一个浮点矩形。通过比较使用SwingUtilities.layoutComponentLabel,可以看到边界向上舍入一个半像素:字体可能会移动一个像素部分以具有锐利的边缘。

【讨论】:

    猜你喜欢
    • 2023-02-04
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多