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

使用Graphics2D旋转JLabel后更新文本,新旧文本重叠

解决旋转JLabel时间更新时文字重叠的问题

首先咱们来拆解下你遇到的问题:分钟更新时新旧数字重叠,秒更新却没异常,核心是两个原因在作怪:

问题根源

  1. 过度频繁的重绘请求:你的ClockWidget类里每1毫秒就调用一次setText,这会导致大量重绘请求积压,Swing的事件调度线程忙不过来,旧内容还没被清除就绘制了新内容,自然出现重叠。
  2. 旋转绘制时背景清除不彻底:在RotatedJLabel的paintComponent方法中,你直接在原Graphics对象上做旋转,裁剪区域还是旋转前的旧范围,导致super.paintComponent(g)无法完整清除组件背景——尤其是分钟文本宽度变化时(比如从09变成10),旧的像素没被完全覆盖。

修复方案(基于现有代码修改)

步骤1:降低时间更新频率

先把ClockWidget的更新频率改成每秒一次,完全没必要毫秒级刷新:

@Override
public void run() {
    while(running) {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm:ss a");
        currentTime = simpleDateFormat.format(calendar.getTime());
        setText(currentTime);
        try {
            // 每秒更新一次,减轻重绘压力
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

步骤2:修复旋转绘制逻辑

修改RotatedJLabel的paintComponent方法,创建独立的Graphics对象,确保背景被彻底清除:

@Override
protected void paintComponent(Graphics g) {
    // 创建Graphics2D副本,避免干扰全局绘制状态
    Graphics2D g2 = (Graphics2D) g.create();
    
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
    double centerX = getWidth() / 2.0;
    double centerY = getHeight() / 2.0;
    
    // 以组件中心为原点旋转90度
    g2.rotate(Math.toRadians(90), centerX, centerY);
    
    // 先绘制背景,彻底清除旧内容
    g2.setColor(getBackground());
    g2.fillRect(0, 0, getWidth(), getHeight());
    
    // 调用父类方法绘制文本
    super.paintComponent(g2);
    
    // 释放创建的Graphics对象
    g2.dispose();
}

替代方案:自定义JPanel绘制旋转文本

如果想更灵活地控制绘制逻辑,可以放弃继承JLabel,改用JPanel自己绘制旋转文本,完全避开JLabel默认绘制逻辑的干扰:

自定义RotatedClockPanel类

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JPanel;

public class RotatedClockPanel extends JPanel implements Runnable {
    private String currentTime;
    private boolean running;
    private Font font;
    private Color textColor;

    public RotatedClockPanel() {
        running = true;
        font = new Font("Arial", Font.PLAIN, 36);
        textColor = Color.WHITE;
        setBackground(Color.BLUE);
    }

    @Override
    public void run() {
        while(running) {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("hh:mm:ss a");
            currentTime = simpleDateFormat.format(calendar.getTime());
            repaint();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 先绘制组件背景,清除旧内容
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g.create();
        
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        // 计算组件中心
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        
        // 以中心为原点旋转90度
        g2.rotate(Math.toRadians(90), centerX, centerY);
        
        // 设置字体和文本颜色
        g2.setFont(font);
        g2.setColor(textColor);
        
        // 计算文本居中的位置
        int textWidth = g2.getFontMetrics().stringWidth(currentTime);
        int textHeight = g2.getFontMetrics().getAscent();
        int drawX = centerX - textWidth / 2;
        int drawY = centerY + textHeight / 2;
        
        // 绘制时间文本
        g2.drawString(currentTime, drawX, drawY);
        
        g2.dispose();
    }

    public void disable() {
        running = false;
    }

    @Override
    public void setFont(Font font) {
        this.font = font;
        repaint();
    }

    public void setForeground(Color textColor) {
        this.textColor = textColor;
        repaint();
    }
}

在Driver中替换使用这个Panel

注意旋转后组件的宽高要互换(原来的250宽100高,旋转90度后设置为100宽250高,适配文本显示):

public void initClockWidgit() {
    RotatedClockPanel clockPanel = new RotatedClockPanel();
    clockPanel.setFont(new Font("Arial", Font.PLAIN, 36));
    clockPanel.setForeground(Color.WHITE);
    clockPanel.setBackground(Color.BLUE);
    // 旋转后宽高互换,让文本显示更合理
    clockPanel.setBounds((int) (screenSize.getWidth() * 0.90), (int) (screenSize.getHeight() * 0.10), 100, 250);
    add(clockPanel);
    new Thread(clockPanel).start();
}

这样修改后,无论是分钟还是秒更新,都不会出现文字重叠的问题了,绘制逻辑也更清晰可控。

内容的提问来源于stack exchange,提问作者Matt Miller

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:22:33