Java Swing棋盘侧边文字底部被截断问题求助
棋盘坐标文字底部截断问题解决
问题描述
开发棋盘程序时,使用JLayeredPane分层放置两个JPanel:底部Sideline面板显示棋盘坐标,顶部面板承载棋盘。但侧边坐标文字底部出现截断情况。

原代码如下:
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; public class Main { public static void main(String[] args) { JFrame frame = new JFrame(); JLayeredPane lPane = new JLayeredPane(); Sideline sl = new Sideline(); frame.setTitle("Chess MF"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.setLocation(350, 200); // setup Center Panel frame.getContentPane().add(lPane, BorderLayout.CENTER); lPane.setPreferredSize(new Dimension(540, 540)); sl.setBounds(20, 20, sl.getWholeSize(), sl.getWholeSize()); lPane.add(sl, Integer.valueOf(0)); frame.pack(); frame.setVisible(true); } } class Sideline extends JPanel { private int sidelineSize = 20; private int wholeSize = 500; private int fieldSize = 60; Font font = new Font("Arial", Font.BOLD, 20); @Override public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHints(rh); g2.setFont(font); int row, col; int x, y; String rowName = "12345678"; String colName = "abcdefgh"; for (row = 0; row < 8; row++) { x = 0; y = row * fieldSize + sidelineSize + g.getFont().getSize() / 2; g.drawString(String.valueOf(rowName.charAt(row)), x, y); } for (col = 0; col < 8; col++) { x = col * fieldSize + sidelineSize + g.getFont().getSize(); y = 8 * fieldSize + sidelineSize; g.drawString(String.valueOf(colName.charAt(col)), x, y); } } public int getSidelineSize() { return sidelineSize; } public int getWholeSize() { return wholeSize; } }
问题原因
- 面板尺寸不足:
Sideline的wholeSize设为500,底部文字绘制的y坐标计算为8*60+20=500,刚好等于面板高度。而drawString的y参数是文字基线位置,文字下半部分会超出面板边界被截断。 - 字体位置计算错误:仅用
font.getSize()/2估算垂直位置,没有考虑字体的实际基线、上升/下降高度,导致文字位置偏下。 - 未处理面板内边距:JPanel默认存在内边距,进一步压缩了实际可绘制区域。
解决方法
1. 调整面板尺寸,预留文字空间
增大面板整体尺寸,给底部文字留出足够的显示空间。
2. 使用FontMetrics精准计算文字位置
通过FontMetrics获取字体的基线、上升高度等信息,确保文字完全在面板可视范围内。
3. 重写getPreferredSize方法
让面板自己报告合适的尺寸,替代硬编码的setBounds,更符合Swing布局规范。
修改后的代码
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JFrame; import javax.swing.JLayeredPane; import javax.swing.JPanel; public class Main { public static void main(String[] args) { JFrame frame = new JFrame(); JLayeredPane lPane = new JLayeredPane(); Sideline sl = new Sideline(); frame.setTitle("Chess MF"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setResizable(false); frame.setLocation(350, 200); frame.getContentPane().add(lPane, BorderLayout.CENTER); lPane.setPreferredSize(new Dimension(560, 560)); // 利用面板自身的PreferredSize设置边界 sl.setBounds(20, 20, sl.getPreferredSize().width, sl.getPreferredSize().height); lPane.add(sl, Integer.valueOf(0)); frame.pack(); frame.setVisible(true); } } class Sideline extends JPanel { private int sidelineSize = 20; private int fieldSize = 60; Font font = new Font("Arial", Font.BOLD, 20); @Override public void paintComponent(Graphics g) { super.paintComponent(g); // 必须调用父类方法,确保面板正确绘制 Graphics2D g2 = (Graphics2D) g; RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHints(rh); g2.setFont(font); FontMetrics fm = g2.getFontMetrics(); int fontAscent = fm.getAscent(); // 字体基线到顶部的高度 int fontHeight = fm.getHeight(); // 字体总高度 int row, col; int x, y; String rowName = "12345678"; String colName = "abcdefgh"; // 绘制左侧行号 for (row = 0; row < 8; row++) { x = sidelineSize / 2; // 水平居中 // 计算垂直位置:行起始位置 + 侧边栏高度 + 字体上升高度(确保文字垂直居中) y = row * fieldSize + sidelineSize + fontAscent; g.drawString(String.valueOf(rowName.charAt(row)), x, y); } // 绘制底部列号 for (col = 0; col < 8; col++) { // 水平居中:列起始位置 + 侧边栏高度 + 单元格宽度/2 - 文字宽度/2 x = col * fieldSize + sidelineSize + fieldSize/2 - fm.stringWidth(String.valueOf(colName.charAt(col)))/2; // 垂直位置:棋盘总高度 + 侧边栏高度 - 字体下降高度(避免底部截断) y = 8 * fieldSize + sidelineSize + fontHeight - fm.getDescent(); g.drawString(String.valueOf(colName.charAt(col)), x, y); } } @Override public Dimension getPreferredSize() { // 面板总尺寸:棋盘宽度(8*fieldSize) + 左侧侧边栏,高度:棋盘高度(8*fieldSize) + 顶部侧边栏 + 字体高度 return new Dimension(8 * fieldSize + sidelineSize, 8 * fieldSize + sidelineSize + font.getSize()); } }
关键修改点
- 调用
super.paintComponent(g):确保面板的背景和内边距正确处理 - 使用
FontMetrics获取字体的精准尺寸,避免位置估算错误 - 重写
getPreferredSize:让面板自动计算合适的尺寸,适配文字显示 - 调整底部文字的y坐标,预留字体下降部分的空间,避免截断
内容的提问来源于stack exchange,提问作者JoeFuzz
相关产品推荐
相关产品推荐

