Java使用drawString垂直绘制文本时出现前置间隙的问题排查与修复
Java使用drawString垂直绘制文本时出现前置间隙的问题排查与修复
嘿,我来帮你搞定这个垂直文本绘制的间隙问题~ 你遇到的奇怪间隙,本质是旋转后坐标系变化导致文本绘制的基准坐标计算错误,还有对drawString的绘制基准点理解不到位,咱们一步步来解决:
问题根源分析
- 坐标系旋转后的坐标映射错误:当你围绕矩形中心旋转文本时,原来的水平坐标系会跟着旋转,此时你用原坐标系的
r.x(矩形左边界)作为旋转后文本的x坐标,已经不再是你期望的“矩形垂直边缘”位置了。 drawString的绘制基准点误解:drawString默认是基于文本的**基线(baseline)**来绘制的,旋转后基线的方向也跟着改变了,直接用y0(矩形中心y坐标)会导致文本偏移。- 文本尺寸的方向混淆:旋转90度后,原来的文本宽度(
textWidth)会变成垂直方向的高度,原来的高度(textHeight)会变成水平方向的宽度,你没有对应调整这个尺寸关系。
修复方案与代码调整
我们重新调整drawLabel方法里的坐标计算逻辑,确保旋转后的文本起始端刚好贴合矩形的垂直边缘:
private void drawLabel(Graphics g, String text, double rotation, Rectangle r) { final int AXIS_OFFSET = 20; final int TOP_BUFFER = 30; // where additional text is drawn Graphics2D g2d = (Graphics2D)g.create(); g2d.setFont(font); FontMetrics fontMetrics = g2d.getFontMetrics(); int textHeight = fontMetrics.getHeight(); int textWidth = fontMetrics.stringWidth(text); int rectCenterX = r.x + r.width / 2; int rectCenterY = r.y + r.height / 2; // 绘制辅助线和矩形(保留你的调试代码) g2d.drawLine(rectCenterX, getBounds().y, rectCenterX, getBounds().y + getBounds().height); g2d.drawLine(getBounds().x, rectCenterY, getBounds().x + getBounds().width, rectCenterY); g2d.drawRect(r.x, r.y, r.width, r.height); // 先旋转坐标系 g2d.rotate(rotation, rectCenterX, rectCenterY); // 根据旋转方向计算文本的绘制坐标,让文本起始端贴合矩形垂直边缘 int drawX, drawY; if (rotation == -Math.PI / 2) { // 顺时针旋转90度:文本向下排列,起始端对齐矩形左垂直边缘 // 旋转后,原矩形的左边缘x坐标对应旋转后的y方向位置,调整基线对齐 drawX = r.x; drawY = rectCenterY + textWidth / 2 - fontMetrics.getDescent(); } else if (rotation == Math.PI / 2) { // 逆时针旋转90度:文本向上排列,起始端对齐矩形左垂直边缘 drawX = r.x; drawY = rectCenterY - textWidth / 2 + fontMetrics.getAscent(); } else { // 其他旋转角度的默认处理(这里只针对垂直旋转) drawX = rectCenterX - textWidth / 2; drawY = rectCenterY + fontMetrics.getDescent(); } // 只保留正确的一次绘制 g2d.drawString(text, drawX, drawY); g2d.dispose(); }
关键调整点说明
- 旋转后坐标的重新映射:针对顺时针/逆时针两种垂直旋转方向,分别计算文本的y坐标(因为旋转后y轴方向改变了),利用
textWidth(原水平宽度,旋转后变成垂直方向的长度)来居中对齐,同时通过fontMetrics的ascent和descent调整基线位置,消除间隙。 - 移除多余的绘制代码:你原来的代码里调用了两次
drawString,这会导致文本重叠,只保留计算好的一次绘制即可。 - 明确矩形中心变量名:把
x0/y0改成更清晰的rectCenterX/rectCenterY,避免混淆。
调整后,你会看到文本的起始端刚好贴合矩形的垂直边缘,不会再有奇怪的间隙了。如果需要调整文本在矩形内的上下位置,可以微调drawY的计算逻辑,比如增减偏移量。
备注:内容来源于stack exchange,提问作者Alex B.
相关产品推荐
相关产品推荐

