java – Swing中带缩放图形的字符串的边界 – 可能的错误
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java – Swing中带缩放图形的字符串的边界 – 可能的错误,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5203字,纯文字阅读大概需要8分钟。
内容图文
![java – Swing中带缩放图形的字符串的边界 – 可能的错误](/upload/InfoBanner/zyjiaocheng/795/dbf02c68213441fba9b43aa8df6316ef.jpg)
正如related question中已经提到的:
There are many (many) questions about computing the size (width or height) of a string that should be painted into a Swing component. And there are many proposed solutions.
但是,最常用和推荐的解决方案(根据我迄今为止的经验,至少计算大多数情况下的正确界限)再次在某些条件下显示出相当奇怪的行为.
以下示例显示了我目前认为的普通错误:
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.Locale;
public class StringBoundsBugTest
{
public static void main(String[] args)
{
Font font = new Font("Dialog", Font.PLAIN, 10);
BufferedImage bi = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = bi.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
for (int i=1; i<30; i++)
{
double scaling = 1.0 / i;
AffineTransform oldAt = g.getTransform();
g.scale(scaling, scaling);
FontRenderContext fontRenderContext = g.getFontRenderContext();
Rectangle2D bounds =
font.getStringBounds("Test", fontRenderContext);
g.setTransform(oldAt);
System.out.printf(Locale.ENGLISH,
"Scaling %8.5f, width %8.5f\n",
scaling, bounds.getWidth());
}
}
}
该程序创建一个Graphics2D实例(无论它来自JComponent还是BufferedImage),然后将各种缩放因子应用于此图形对象,并使用图形对象的FontRenderContext计算字符串的边界.
根据我的理解,图形对象的缩放因子不应该影响边界(人们可能期望在这里有不同的东西,但这无论如何都是这样).
不过,上面的程序输出对我来说(JDK 1.8.0_31)是
Scaling 1.00000, width 19.44824
Scaling 0.50000, width 19.44824
Scaling 0.33333, width 19.32669
Scaling 0.25000, width 19.44824
Scaling 0.20000, width 19.44824
Scaling 0.16667, width 19.32669
Scaling 0.14286, width 19.14436
Scaling 0.12500, width 19.44824
Scaling 0.11111, width 19.14436
Scaling 0.10000, width 19.44824
Scaling 0.09091, width 19.38747
Scaling 0.08333, width 18.96204
Scaling 0.07692, width 18.96204
Scaling 0.07143, width 18.71893
Scaling 0.06667, width 19.14436
Scaling 0.06250, width 19.44824
Scaling 0.05882, width 18.59738
Scaling 0.05556, width 18.59738
Scaling 0.05263, width 18.47583
Scaling 0.05000, width 19.44824
Scaling 0.04762, width 0.00000
Scaling 0.04545, width 0.00000
Scaling 0.04348, width 0.00000
Scaling 0.04167, width 0.00000
Scaling 0.04000, width 0.00000
Scaling 0.03846, width 0.00000
Scaling 0.03704, width 0.00000
Scaling 0.03571, width 0.00000
Scaling 0.03448, width 0.00000
人们可以看到计算出的大小奇怪地摆动约18-19.这表明大小应该确实是“固定的”,无论应用于图形的缩放,我不介意可能来自舍入问题的小错误和一般的字体相关计算的荒谬复杂性.
但是,不可接受的是,对于某个比例因子,计算出的大小明显降至零.发生这种情况的缩放因子取决于字体大小,但即使对于较大的字体,也会分别使用较小的缩放因子.
当然,有一个明显的,高级别的解释:某处,在字体相关的Swing类(如FontRenderContext等)深处,执行一些计算,使用图形的缩放因子缩放某些值,然后…将其转换为int . (同样可能是上述问题中的问题).
一个明显的解决方法可能是创建一个固定的FontRenderContext,并将其用于各处与字体相关的计算.但这会破坏通常与图形绑定的字体相关计算的目的:使用与绘画不同的FontRenderContext进行计算可能会在计算的大小和实际绘制的大小之间引入偏差.
有没有人有一个干净,可靠的解决方案来计算Swing中的字符串边界,无论字体大小如何,无论应用于图形的缩放因子如何?
解决方法:
实际上FontRenderContext有4个字段
public class FontRenderContext {
private transient AffineTransform tx;
private transient Object aaHintValue;
private transient Object fmHintValue;
private transient boolean defaulting;
所以变换是背景的一部分.如果你的比例1/3当然有一些四舍五入.
因此,您可以在获取FontRenderContext之前为图形将AffineTransform设置为正常(例如,无转换和无比例).
或者您可以创建自己并在任何地方重复使用它
FontRenderContext frc=new FontRenderContext(g.getTransform(), //of just replace with new AffineTransform(),
g.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING),
g.getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS));
关于GlyphVector创建.它也可以是一种选择.
检查Font.getStringBounds()源代码
public Rectangle2D getStringBounds( String str, FontRenderContext frc) {
char[] array = str.toCharArray();
return getStringBounds(array, 0, array.length, frc);
}
public Rectangle2D getStringBounds(char [] chars,
int beginIndex, int limit,
FontRenderContext frc) {
//some checks skipped
boolean simple = values == null ||
(values.getKerning() == 0 && values.getLigatures() == 0 &&
values.getBaselineTransform() == null);
if (simple) {
simple = ! FontUtilities.isComplexText(chars, beginIndex, limit);
}
if (simple) {
GlyphVector gv = new StandardGlyphVector(this, chars, beginIndex,
limit - beginIndex, frc);
return gv.getLogicalBounds();
因此,您可以看到StandardGlyphVector是为简单情况创建的(当文本没有例如RTL内容时).在相反的情况下使用TextLayout.
结果可能是这样的
private static Rectangle2D getBounds(Graphics2D g, String text) {
FontRenderContext frc=new FontRenderContext(new AffineTransform(),
g.getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING),
g.getRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS));
GlyphVector gv = new StandardGlyphVector(g.getFont(), text.toCharArray(), 0,
text.length(), frc);
return gv.getLogicalBounds();
}
内容总结
以上是互联网集市为您收集整理的java – Swing中带缩放图形的字符串的边界 – 可能的错误全部内容,希望文章能够帮你解决java – Swing中带缩放图形的字符串的边界 – 可能的错误所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。