You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:47:33