實現平滑跑馬燈,必須精確掌握文字在特定字體下的像素寬度:
FontMetrics metrics = label.getFontMetrics(label.getFont());
int textHeight = metrics.getHeight(); // 字體高度 (固定)
int textWidth = metrics.stringWidth(text); // 字串像素寬度
經驗值:半形空格約 3 像素。
Test.javaimport java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test {
private JFrame frame;
private String scrolledText;
private String str = "滾動文字 Demo";
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try { new Test().frame.setVisible(true); }
catch (Exception e) { e.printStackTrace(); }
});
}
public Test() { initialize(); }
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 500, 375);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(Color.WHITE);
frame.getContentPane().add(panel, BorderLayout.NORTH);
final JLabel label = new JLabel("New JLabel");
panel.add(label);
label_scrolledText(label);
// 視窗大小變更時重新計算填充空格
frame.addComponentListener(new ComponentAdapter() {
@Override public void componentResized(ComponentEvent e) {
label_scrolledText(label);
}
});
}
public void label_scrolledText(JLabel label) {
this.scrolledText = this.str;
label.setText(scrolledText);
FontMetrics metrics = label.getFontMetrics(label.getFont());
int textW = metrics.stringWidth(label.getText());
Dimension frameSize = frame.getSize();
// 計算需要填充的空格數,使文字寬度略小於視窗寬度
for (int i = 1; i <= (frameSize.width - textW) / 3 - 3; i++) {
scrolledText += " ";
}
label.setText(scrolledText);
new Thread(new TextChanger(label)).start();
}
}
TextChanger.javaimport javax.swing.JLabel;
public class TextChanger implements Runnable {
private final JLabel label;
public TextChanger(JLabel label) { this.label = label; }
@Override
public void run() {
try {
while (true) {
String text = label.getText();
if (text.length() > 1) {
// 首字移至尾部,形成循環滾動
text = text.substring(1) + text.charAt(0);
label.setText(text);
label.repaint();
}
Thread.sleep(50); // 幀率 ~20fps
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
repaint() 觸發重繪substring(1) + charAt(0) 實現平滑單字元位移
javax.swing.Timer 替代 Thread.sleep 更符合 Swing 執行緒規範