在java中获取字符串大小(没有可用的图形对象)
我正在尝试编写一个应用程序,它需要使用Java中的在java中获取字符串大小(没有可用的图形对象),java,string,bounds,graphics2d,Java,String,Bounds,Graphics2d,我正在尝试编写一个应用程序,它需要使用Java中的Graphics2D类来绘制许多字符串。我需要得到每个字符串对象的大小(以计算每个字符串的确切位置)。 有太多的字符串,在调用paint()方法之前应该执行一次,并且只在程序开始时执行一次(因此我还没有Graphics2D对象)。我知道有一个方法Font.getStringBounds(),但它需要一个FontRenderContext对象作为参数 当我尝试创建自己的对象时: FontRenderContext frc = new FontRen
Graphics2D
类来绘制许多字符串。我需要得到每个字符串对象的大小(以计算每个字符串的确切位置)。
有太多的字符串,在调用paint()
方法之前应该执行一次,并且只在程序开始时执行一次(因此我还没有Graphics2D
对象)。我知道有一个方法Font.getStringBounds()
,但它需要一个FontRenderContext
对象作为参数
当我尝试创建自己的对象时:
FontRenderContext frc = new FontRenderContext(MyFont.getTransform(), true, true)
然后获取字符串边界,我总是使用Graphics2D.getFontRenderContext()
内的paint()
方法获取FontRenderContext
时得到的大小不同。差异不大(大约1E-3),但我想知道为什么会有任何差异
然而,有没有更好更安全的方法来获取字符串的大小
Thnx可提前获得任何帮助 与全班同学一起尝试;该方法返回字符串的大小。
例如:
JComponent c = getSomeKindOfJComponent();
FontMetrics fm = c.getFontMetrics(c.getFont()); // or another font
int strw = fm.stringWidth("My text");
下面是一段代码,它做了类似的事情——编写它是为了将字符串缩写为给定的像素数
public static String abbreviate(final Graphics2D g2, final String text, final int fitToWidth) {
// define how many characters in the caption can be drawn
final FontMetrics fm = g2.getFontMetrics();
Rectangle2D textBounds = fm.getStringBounds(text, g2);
int count = text.length();
while ((textBounds.getWidth() > fitToWidth) && (count > 4)) {
textBounds = fm.getStringBounds(text.substring(0, count--), g2);
}
return count == text.length() ? text : StringUtils.abbreviate(text, count);
}
除了使用
FontMetrics
,还可以使用JLabel
来确定未格式化文本和(基本HTML)呈现文本的大小。这里有一个例子
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.ImageIcon;
/** Sample code obtained from a thread on the Oracle forums that I cannot
locate at this instant. My question was related to an unexpected rendering of
JLabel. It was resolved by the 'added this' line courtesy of Darryl Burke. */
public class LabelRenderTest {
String title = "<html><body style='width: 160px; padding: 8px'>"
+ "<h1>Do U C Me?</h1>"
+ "Here is a long string that will wrap. "
+ "The effect we want is a multi-line label.";
LabelRenderTest() {
BufferedImage image = new BufferedImage(
640,
480,
BufferedImage.TYPE_INT_RGB);
Graphics2D imageGraphics = image.createGraphics();
GradientPaint gp = new GradientPaint(
20f, 20f, Color.blue,
620f, 460f, Color.white);
imageGraphics.setPaint(gp);
imageGraphics.fillRect(0, 0, 800, 600);
JLabel textLabel = new JLabel(title);
textLabel.setSize(textLabel.getPreferredSize()); // <==== added this
Dimension d = textLabel.getPreferredSize();
BufferedImage bi = new BufferedImage(
d.width,
d.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.createGraphics();
g.setColor(new Color(255, 255, 255, 128));
g.fillRoundRect(
0,
0,
bi.getWidth(null),
bi.getHeight(null),
15,
10);
g.setColor(Color.black);
textLabel.paint(g);
Graphics g2 = image.getGraphics();
g2.drawImage(bi, 20, 20, null);
ImageIcon ii = new ImageIcon(image);
JLabel imageLabel = new JLabel(ii);
JOptionPane.showMessageDialog(null, imageLabel);
}
public static void main(String[] args) {
LabelRenderTest ist = new LabelRenderTest();
}
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.GradientPaint;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.image.buffereImage;
导入javax.swing.JOptionPane;
导入javax.swing.JLabel;
导入javax.swing.ImageIcon;
/**从Oracle论坛上的线程获得的示例代码,我无法
在这一刻找到。我的问题与一次意外的渲染有关
杰拉贝尔。由Darryl Burke提供的“添加此”行解决了此问题*/
公共类LabelRenderTest{
String title=“”
+“你喜欢我吗?”
+“这是一条可以缠绕的长字符串。”
+“我们想要的效果是多行标签。”;
LabelRenderTest(){
BuffereImage=新的BuffereImage(
640,
480,
BuffereImage.TYPE_INT_RGB);
Graphics2D imageGraphics=image.createGraphics();
GradientPaint gp=新的GradientPaint(
20f,20f,蓝色,
620f,460f,彩色。白色);
图像图形.setPaint(gp);
imageGraphics.fillRect(0,0,800600);
JLabel textLabel=新的JLabel(标题);
textLabel.setSize(textLabel.getPreferredSize());//您可能还想查看SwingUtilities.computeStringWidth
出于历史原因,我认为他最初是这样做的(jruby java pseucodoe)
不,啊,刚娜,发生了
原因是您从FRC中寻找的渲染和计算是特定于图形上下文的,即特定的Graphics2D对象。您感兴趣的对象是运行时交给您的对象-它与其他对象不同(您必须假设)
您可以使用其他一些Graphics2D中的FRC计算任意多的值,但是当您尝试在运行时将计算结果与Graphics2D paintComponent一起使用时,无论发生什么情况,您的计算结果都是徒劳的,这就是您将要使用的Graphics2D
所以,是的,这很好,但它完全是理论上的。所有这些好的信息都被有效地锁定在FRC中,因为如果没有确切的图形2d,属性字符串实际上将被绘制,FRC比无用还要糟糕——这是一个你可能会尝试接受的幻觉
这是有道理的,因为一切实际上都取决于运行时得到的图形2D。因此,最好的做法是接受它并编写代码,从paintComponent内部调用任何对象和任何需要进行的专门计算,并围绕这一事实构建设计
<>我是一个很好的问题,也是一件好事,希望你能做,你不能。你看到其他人在网络上的其他地方,在其他论坛上询问这个问题。注意缺少有用的答案和/或震耳欲聋的沉默。 String String不返回有效的字符串大小,因为它不考虑反走样和其他特征。(如字符之间的间距)。此方法并非在所有情况下都有效。如果“JComponent c”您得到的尚未初始化/验证,其字体和fontMetrics将与以后的不一样,并且您的字体度量将关闭。它不会总是这样,但像高DPI模式之类的东西可能会触发这种情况。这不是我需要的-我想在没有Graphics2D对象的情况下获得精确的字符串边界。@coder89嗯..Graph的属性ics2D实例在应用程序的整个生命周期中可能会有所不同。正如您所指出的,需要考虑“抗锯齿和其他功能”,如果没有Graphics2D的特定实例,这是不可能的。它将宽度作为整数返回-我需要更精确的东西
font = UIManager.getFont("Label.font")
frc = java.awt.font.FontRenderContext.new(font.transform, true, true)
textLayout = java.awt.font.TextLayout.new(text, font, frc)
textLayout.bounds.width