使用字体
字体名(font face name)指定一种字体,字体名由字体族名(font family name)和一个可选的后缀(如果"Bold")组成,例如,“Helvetica”和"Helvetica Bold"都属于名为“Helvetica”字体族的字体。
要想知道某台特定计算机上可用的字体,可以调用GraphicsEnvironment类的getAvailableFontFamilyNames方法,这个方法返回一个字符串数组,其中包含了所有可用的字体名,GraphicsEnvironment类描述了用户系统的图像上下文,为了得到这个类的对象,需要调用静态的getLocalGraphicsEnvironment方法。
打印系统上的所有字体名
package font;
import java.awt.GraphicsEnvironment;
public class ListFonts {
public static void main(String[] args) {
String[] fontNames = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
for (String fontName : fontNames) {
System.out.println(fontName);
}
}
}
结果:
这些字体名总是被映射到客户机上的某些实际字体,例如,在Windows系统重,SansSerif将被映射到Arial。
另外,Oracle JDK总是包含3个字体族,名为Lucida Sans,Lucida Bright,Lucida Sans Typewriter。
要想使用某种字体绘制字符,首先创建一个Font类的对象,需要指定字体名、字体风格和字体大小,下面是构造一个Font对象的例子:
var sansbold14 = new Font("SansSerif",Font.BOLD,14);
第三个参数是以点数目计算的字体大小,排版中普遍使用点数指示字体大小,没英寸包含72个点。
在Font构造器中,提供字体名的位置也可以给出逻辑字体名。可以把Font构造器的第二个参数设置为一下值来指定字体的风格(常规、加粗、斜体或加粗斜体):
Font.PLAIN Font.BOLD Font.ITALIC Font.BOLD + Font.ITALIC
常规字体的字体大小为1点,可以使用deriveFont方法得到所需大小的字体:
Font f = f1.deriveFont(14.0F)
警告:deriveFont方法有两个重载版本,一个(有一个float参数)设置字体的大小,另一个(有一个int参数)设置字体风格,所以f1.deriveFont(14)设置的是字体风格,而不是大小(其结果为斜体,因为14的二进制表示的是ITALIC位为1,而BOLD位为0)。
下面这段代码将使用系统中14点加粗的标准sans serif字体显示字符串"Hello,World":
package draw;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class DrawFontTest {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
var frame = new DrawFontFrame();
frame.setTitle("DrawFontTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
class DrawFontFrame extends JFrame {
public DrawFontFrame() {
add(new DrawFontComponent());
pack();
}
}
class DrawFontComponent extends JComponent {
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 400;
@Override
protected void paintComponent(Graphics g) {
String[] fontNames = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames();
// for (String fontName : fontNames) { System.out.println(fontName); }
ArrayList<String> fontNameList = new ArrayList<>(Arrays.asList(fontNames));
System.out.println(fontNameList.contains("SansSerif"));
var sansbold14 = new Font("SansSerif",Font.BOLD,14);
g.setFont(sansbold14);
var message = "Hello, World!";
g.drawString(message, 75, 100);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
结果:
接下来,将字符串居中,而不是绘制在任意位置,因此,需要知道字符串占据的宽和高的像素数,这两个值取决于下面三个因素:
- 使用的字体
- 字符串
- 绘制字体的设备(用户屏幕)
得到表示屏幕设备字体属性对象,需要调用Graphics2D类中的getFontRenderContext方法。返回一个FontRenderContext类的对象,可以直接将这个对象传递给Font类的getStringBounds方法:
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = sansbold14.getStringBounds(message,context);
getStringBounds方法将返回包围字符串的矩形。
getStringBounds方法返回的矩形宽度是字符串水平方向的宽度,矩形的高度是上坡度、下坡度和行间距的总和,这个矩形始于字符串的基线,矩形顶部的y坐标为负值,因此,可以使用下面的方法获得字符串的宽度、高度和上坡度:
- double stringWidth = bounds.getWidth();
- double stringHeight = bounds.getHeight();
- double ascent = -bounds.getY();
如果需要知道下坡度或行间距,可以使用Font类的getLineMetrics方法,这个方法将返回一个LineMetrics类的对象,获得下坡度和行间距的方法是:
LineMetrics metrics = f.getLineMetrics(message,context);
float descent = metrics.getDescent();//下坡度
float leading = metrics.getLeading();//行间距
注释:如果需要再paintComponent方法外部计算布局大小,不能从Graphics2D对象得到字体绘制上下文,应该换做JComponent类的getFontMetrics方法,然后调用getFontRenderContext:
FontRenderContext context = getFontMetrics(f).getFontRenderContext();
绘制基线和字符串外框矩形
package font;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class FontTest {
public static void main(String[] args) {
EventQueue.invokeLater(()->{
var frame = new FontFrame();
frame.setTitle("FontTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
class FontFrame extends JFrame {
public FontFrame() {
add(new FontComponent());
pack();
}
}
class FontComponent extends JComponent {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
@Override
protected void paintComponent(Graphics g) {
var g2 = (Graphics2D)g;
var message = "Hello, World!";
var f = new Font("Serif",Font.BOLD,36);
g2.setFont(f);
//确定信息大小
FontRenderContext context = g2.getFontRenderContext();
Rectangle2D bounds = f.getStringBounds(message, context);
//设置文本的左上角位置
double x = (getWidth() - bounds.getWidth())/2;
double y = (getHeight() - bounds.getHeight())/2;
//添加上坡线到基线
double ascent = -bounds.getY();
double baseY = y + ascent;
//画这个消息
g2.drawString(message, (int)x, (int)baseY);
g2.setPaint(Color.LIGHT_GRAY);
//画基线
g2.draw(new Line2D.Double(x, baseY, x+bounds.getWidth(), baseY));
//画闭合的矩形
var rect = new Rectangle2D.Double(x, y, bounds.getWidth(), bounds.getHeight());
g2.draw(rect);
}
@Override
public Dimension preferredSize() {
// TODO Auto-generated method stub
return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
java.awt.Font 1.0
- Font(String name,int style,int size),创建一个新字体对象,字体名可以是具体的字体名("Helvetica Bold")或逻辑字体名("Serif","SansSerif"),字体风格可以是Font.PLAIN、FontBOLD、FontITALIC、或FontBOLD+FontITALIC。
- String getFontName(),获得字体名,例如,"Helvetica Bold"。
- String getFamily(),获得字体族名,例如,Helvetica
- String getName(),如果采用逻辑字体名创建字体,将获得逻辑字体名,例如,SansSerif否则,获得字体名。
- Rectangle2D getStringBounds(String s,FontRenderContext context) 1.2,返回包围这个字符串矩形,矩形的起点为基线,矩形顶端的y坐标等于上坡度的负值,矩形的高度等于上坡度,下坡度和行间距之和。宽度等于字符串的宽度。
- LineMetrics getLineMetrics(String s,FontRenderContext context) 1.2,返回确定字符串宽度的一个度量对象。
- Font deriveFont(int style) 1.2
- Font deriveFont(float size) 1.2
- Font deriveFont(int style,float size) 1.2,返回一个新字体,除了有给定的大小和字体风格外,其余与原字体一样。
java.awt.font.LineMetrics 1.2
- float getAscent(),获得字体的上坡度-从基线到大写字母顶端的距离
- float getDescent(),获得字体的下坡度-从基线到坡底的距离。
- float getLeading(),获得字体的行间距-从一行文本底端到下一行文本顶端之间的空隙。
- float getHeight(),获得字体总高度-两条文本基线之间的距离(下坡度+行间距+上坡度)。
java.awt.Graphics2D 1.2
- FontRenderContext getFontRenderContext(),获得这个图形上下文中指定字体特征的字体绘制上下文。
- void drawString(String str,float x,float y),采用当前的字体和颜色绘制一个字符串。
javax.swing.JComponent 1.2
- FontMetrics getFontMetrics(Font f),获取给定字体的字体度量对象,FontMetrics类是LineMetrics类的前身。
java.awt.FontMetrics 1.0
- FontRenderContext getFontRenderContext() 1.2,返回字体的字体绘制上下文。