Java 中图像中的高级文本?
Advanced text in image in Java?
在另一个答案中我找到了这个代码片段:
public void displayText(BufferedImage image, String text, Font font, int x, int y){
Graphics2d g = image.createGraphics();
g.setFont(font);
g.drawString(text, x, y);
g.dispose();
}
但我一直在寻找像这里这样的更精致的东西:
有更好的选择吗?
在任何图形环境中呈现文本是一个复杂的主题。我强烈建议您先查看 Working with Text APIs,因为它将解释您需要了解的许多概念以及可用的 API
还有很多其他的例子,如果你花时间看一下。
这是一个非常简单的示例。就个人而言,我想减少一些重复并更好地利用可重用的概念
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String[] lines = new String[]{
"You can never quit",
"WINNERS",
"never quit and quitters never win"
};
private Font baseFont;
private Font largeFont;
public TestPane() {
baseFont = new Font("Arial", Font.BOLD, 24);
largeFont = baseFont.deriveFont(80f);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
TextLayout line1 = new TextLayout(lines[0], baseFont, g2d.getFontRenderContext());
TextLayout line2 = new TextLayout(lines[1], largeFont, g2d.getFontRenderContext());
TextLayout line3 = new TextLayout(lines[2], baseFont, g2d.getFontRenderContext());
Rectangle2D bounds = line2.getBounds();
double xPos = (getWidth() - bounds.getWidth()) / 2;
double yPos = (getHeight() / 2) + (bounds.getHeight() / 2);
Shape textLine2Shape = line2.getOutline(AffineTransform.getTranslateInstance(xPos, yPos));
g2d.fill(textLine2Shape);
double yOffset = yPos - bounds.getHeight();
xPos = (getWidth() - line1.getBounds().getWidth()) / 2;
Shape textLine1Shape = line1.getOutline(AffineTransform.getTranslateInstance(xPos, yOffset));
g2d.fill(textLine1Shape);
yOffset = yPos + line3.getBounds().getHeight();
xPos = (getWidth() - line3.getBounds().getWidth()) / 2;
g2d.fill(line3.getOutline(AffineTransform.getTranslateInstance(xPos, yOffset)));
Rectangle2D textLine1Bounds = textLine1Shape.getBounds2D();
Rectangle2D textLine2Bounds = textLine2Shape.getBounds2D();
Area whole = new Area(new Rectangle2D.Double(textLine2Bounds.getX(), textLine1Bounds.getY(), textLine2Bounds.getWidth(), textLine1Bounds.getHeight()));
whole.subtract(new Area(textLine1Bounds));
g2d.setClip(whole);
xPos = textLine2Bounds.getX();
yPos = textLine1Bounds.getCenterY();
g2d.draw(new Line2D.Double(xPos, yPos, xPos + textLine2Bounds.getWidth(), yPos));
g2d.dispose();
}
}
}
在另一个答案中我找到了这个代码片段:
public void displayText(BufferedImage image, String text, Font font, int x, int y){
Graphics2d g = image.createGraphics();
g.setFont(font);
g.drawString(text, x, y);
g.dispose();
}
但我一直在寻找像这里这样的更精致的东西:
有更好的选择吗?
在任何图形环境中呈现文本是一个复杂的主题。我强烈建议您先查看 Working with Text APIs,因为它将解释您需要了解的许多概念以及可用的 API
还有很多其他的例子,如果你花时间看一下。
这是一个非常简单的示例。就个人而言,我想减少一些重复并更好地利用可重用的概念
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String[] lines = new String[]{
"You can never quit",
"WINNERS",
"never quit and quitters never win"
};
private Font baseFont;
private Font largeFont;
public TestPane() {
baseFont = new Font("Arial", Font.BOLD, 24);
largeFont = baseFont.deriveFont(80f);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
TextLayout line1 = new TextLayout(lines[0], baseFont, g2d.getFontRenderContext());
TextLayout line2 = new TextLayout(lines[1], largeFont, g2d.getFontRenderContext());
TextLayout line3 = new TextLayout(lines[2], baseFont, g2d.getFontRenderContext());
Rectangle2D bounds = line2.getBounds();
double xPos = (getWidth() - bounds.getWidth()) / 2;
double yPos = (getHeight() / 2) + (bounds.getHeight() / 2);
Shape textLine2Shape = line2.getOutline(AffineTransform.getTranslateInstance(xPos, yPos));
g2d.fill(textLine2Shape);
double yOffset = yPos - bounds.getHeight();
xPos = (getWidth() - line1.getBounds().getWidth()) / 2;
Shape textLine1Shape = line1.getOutline(AffineTransform.getTranslateInstance(xPos, yOffset));
g2d.fill(textLine1Shape);
yOffset = yPos + line3.getBounds().getHeight();
xPos = (getWidth() - line3.getBounds().getWidth()) / 2;
g2d.fill(line3.getOutline(AffineTransform.getTranslateInstance(xPos, yOffset)));
Rectangle2D textLine1Bounds = textLine1Shape.getBounds2D();
Rectangle2D textLine2Bounds = textLine2Shape.getBounds2D();
Area whole = new Area(new Rectangle2D.Double(textLine2Bounds.getX(), textLine1Bounds.getY(), textLine2Bounds.getWidth(), textLine1Bounds.getHeight()));
whole.subtract(new Area(textLine1Bounds));
g2d.setClip(whole);
xPos = textLine2Bounds.getX();
yPos = textLine1Bounds.getCenterY();
g2d.draw(new Line2D.Double(xPos, yPos, xPos + textLine2Bounds.getWidth(), yPos));
g2d.dispose();
}
}
}