如何实现JLabel文本在图标上方且二者左对齐?
解决JLabel文本与图标上方左对齐问题
问题描述
我有一个第三方库创建的JLabel,需要为其设置长度可变的文本和宽度可变的图标,要求文本位于图标上方且二者均左对齐。但当前设置后,文本和图标会相互居中对齐:文本宽度大于图标时,图标相对文本居中;反之则文本相对图标居中。若将水平文本位置从CENTER改为LEFT,文本会跑到图标左侧,而非预期的上方位置。
原测试代码:
public class LabelTest { public static void main(String[] args) { SwingUtilities.invokeLater(LabelTest::new); } public LabelTest() { JFrame frm = new JFrame(); JLabel label = new JLabel("Hallo World"); label.setIcon(createIcon(100)); label.setVerticalTextPosition(SwingConstants.TOP); label.setHorizontalTextPosition(SwingConstants.CENTER); label.setHorizontalAlignment(SwingConstants.LEFT); frm.add(label); frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); frm.setSize(300, 200); frm.setLocationRelativeTo(null); frm.setVisible(true); } private Icon createIcon(int width) { BufferedImage img = new BufferedImage(width, 20, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); g.setColor(Color.BLUE); g.fillRect(0, 0, width, 20); g.dispose(); return new ImageIcon(img); } }
解决方案
默认JLabel的组合绘制逻辑会让文本和图标以最大宽度为基准居中对齐,要实现左对齐,需自定义JLabel并重写绘制逻辑。如果是第三方库的JLabel,只需将下面的JLabel替换为第三方的标签类即可。
自定义左对齐标签类
import javax.swing.*; import java.awt.*; public class LeftTopAlignedLabel extends JLabel { public LeftTopAlignedLabel(String text, Icon icon) { super(text, icon, SwingConstants.LEFT); setVerticalTextPosition(SwingConstants.TOP); setHorizontalTextPosition(SwingConstants.CENTER); } @Override protected void paintComponent(Graphics g) { Icon icon = getIcon(); String text = getText(); if (icon == null && text == null) { super.paintComponent(g); return; } Graphics2D g2d = (Graphics2D) g.create(); Insets insets = getInsets(); int x = insets.left; int y = insets.top; // 绘制图标,左对齐 if (icon != null) { icon.paintIcon(this, g2d, x, y); y += icon.getIconHeight() + getIconTextGap(); } // 绘制文本,左对齐 if (text != null && !text.isEmpty()) { FontMetrics fm = g2d.getFontMetrics(); g2d.setColor(getForeground()); g2d.drawString(text, x, y + fm.getAscent()); } g2d.dispose(); } @Override public Dimension getPreferredSize() { Icon icon = getIcon(); String text = getText(); Insets insets = getInsets(); int width = insets.left + insets.right; int height = insets.top + insets.bottom; if (icon != null) { width = Math.max(width, icon.getIconWidth() + insets.left + insets.right); height += icon.getIconHeight(); } if (text != null && !text.isEmpty()) { FontMetrics fm = getFontMetrics(getFont()); int textWidth = fm.stringWidth(text); width = Math.max(width, textWidth + insets.left + insets.right); height += fm.getHeight() + getIconTextGap(); } return new Dimension(width, height); } }
修改后的测试代码
import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; public class LabelTest { public static void main(String[] args) { SwingUtilities.invokeLater(LabelTest::new); } public LabelTest() { JFrame frm = new JFrame(); // 使用自定义标签替代原JLabel JLabel label = new LeftTopAlignedLabel("Hallo World", createIcon(100)); frm.add(label); frm.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); frm.setSize(300, 200); frm.setLocationRelativeTo(null); frm.setVisible(true); } private Icon createIcon(int width) { BufferedImage img = new BufferedImage(width, 20, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); g.setColor(Color.BLUE); g.fillRect(0, 0, width, 20); g.dispose(); return new ImageIcon(img); } }
说明
- 重写
paintComponent方法,手动控制图标和文本的绘制起点,确保二者都从组件内边距的左侧开始绘制,文本位于图标下方(通过getIconTextGap控制间距)。 - 重写
getPreferredSize方法,计算组件的合适尺寸,确保能完整显示文本和图标,避免布局异常。
内容的提问来源于stack exchange,提问作者Sergiy Medvynskyy
相关产品推荐
相关产品推荐

