我需要编写一个绘制居中String的通用方法。为此,我需要知道String的宽度,并计算出我有不同的选择:
Rectangle2D rect=Toolkit.getDefaultToolkit().getFontMetrics(gc.getFont()).getStringBounds(text, gc);
或
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
Rectangle2D rect=gc.getFont().getStringBounds(text, frc);
或
FontMetrics metrics = g.getFontMetrics(font);
metrics.stringWidth(text)
但是我使用哪种方法都没关系,大约需要1秒钟来计算,这太疯狂了,我在Macbook 3,1 GHz Intel Core i7上的Java 1.8.0_121中使用Eclipse,太疯狂了!
这是怎么了?
第一个示例:
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
Container cp = jf.getContentPane();
MyCanvas1 tl = new MyCanvas1();
cp.add(tl);
jf.setSize(300, 200);
jf.setVisible(true);
}
}
class MyCanvas1 extends JComponent {
public void paint(Graphics g) {
long start=System.currentTimeMillis();
Graphics2D g2 = (Graphics2D) g;
drawCenteredString(g2, "Example", getBounds(), g.getFont());
System.out.println("executed in:"+(System.currentTimeMillis()-start));
}
public void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
FontMetrics metrics = g.getFontMetrics(font);
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
// Determine the Y coordinate for the text (note we add the ascent, as in java 2d 0 is top of the screen)
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
// Set the font
g.setFont(font);
// Draw the String
g.drawString(text, x, y);
}
}
在以下位置执行:922
示例2:
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
Container cp = jf.getContentPane();
MyCanvas1 tl = new MyCanvas1();
cp.add(tl);
jf.setSize(300, 200);
jf.setVisible(true);
}
}
class MyCanvas1 extends JComponent {
public void paint(Graphics g) {
long start=System.currentTimeMillis();
Graphics2D g2 = (Graphics2D) g;
drawCenteredString(g2, "Example", getBounds(), g.getFont());
System.out.println("executed in:"+(System.currentTimeMillis()-start));
}
public void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
Rectangle2D rect2=font.getStringBounds(text, frc);
// Draw the String
g.drawString(text, (int) (rect.width/2-rect2.getWidth()/2),(int) (rect.height/2-rect2.getHeight()/2));
}
}
执行于:916
示例3:
import java.awt.Container;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
JFrame jf = new JFrame("Demo");
Container cp = jf.getContentPane();
MyCanvas1 tl = new MyCanvas1();
cp.add(tl);
jf.setSize(300, 200);
jf.setVisible(true);
}
}
class MyCanvas1 extends JComponent {
public void paint(Graphics g) {
long start=System.currentTimeMillis();
Graphics2D g2 = (Graphics2D) g;
drawCenteredString(g2, "Example", getBounds(), g.getFont());
System.out.println("executed in:"+(System.currentTimeMillis()-start));
}
public void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
Rectangle2D rect2=Toolkit.getDefaultToolkit().getFontMetrics(font).getStringBounds(text, g);
// Draw the String
g.drawString(text, (int) (rect.width/2-rect2.getWidth()/2),(int) (rect.height/2-rect2.getHeight()/2));
}
}
执行时间:908
似乎其他人也有类似的问题,但没有任何解决办法:
Java: Fastest way to draw text?
有人看到问题可能在哪里吗?
编辑: 只是使用Java 8u221进行的更新具有相同的结果,使用最新的Java 13却得到了一些改进,而不是900左右,它们在700毫秒左右的时间内执行了。。。我不敢相信。。。这似乎在Mac上非常慢。 。不管我使用的Java版本是什么...
EDIT2:
即使执行以下代码:
public class Main {
public static void main(String[] args) {
long start=System.currentTimeMillis();
BufferedImage image = new BufferedImage(300, 300, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
drawCenteredString(g2, "Example", new Rectangle (0,0,300,300), g2.getFont());
System.out.println("executed in:"+(System.currentTimeMillis()-start));
}
public static void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
Rectangle2D rect2=Toolkit.getDefaultToolkit().getFontMetrics(font).getStringBounds(text, g);
// Draw the String
g.drawString(text, (int) (rect.width/2-rect2.getWidth()/2),(int) (rect.height/2-rect2.getHeight()/2));
}
}
我得到:在以下位置执行:1342