Swing JLabel:强制重绘()
Posted
技术标签:
【中文标题】Swing JLabel:强制重绘()【英文标题】:Swing JLabel: Force repaint() 【发布时间】:2011-11-16 06:15:24 【问题描述】:我正在尝试动态地重新绘制 JLabel,但我终其一生都无法弄清楚如何去做。一旦我调整屏幕大小,下面的代码将按预期执行,但不会自行执行代码。
JLabel 左侧有一个小圆圈,绘制在文本左侧的边框区域。圆圈的颜色应根据 FTP 连接(未显示)的健康状况而变化。监控FTP连接的线程在健康发生变化时调用setStatus(int)
方法。
圆圈是在 JLabel 初始化期间绘制的,我正在尝试使用 repaint()
重新执行此代码。
编辑:我也试过玩revalidate()
、invalidate()
和validate()
,但无济于事。
编辑:感谢您指出这一点,我从使用 paintComponent()
开始,然后在不起作用时更改为 paint()
。因此,将其作为答案并不荣耀(抱歉,请与 Oracle 讨论)
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import com.my.package.io.ftp.FTPConnectionListenable;
class StatusLabel extends JLabel implements FTPConnectionListenable
private Integer status;
// Constructor
StatusLabel(final String text)
super(text);
setFont(new Font("Dialog", Font.PLAIN, 10));
setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
@Override
public void paintComponent(final Graphics g)
super.paintComponent(g);
g.setColor(getColor());
g.fillArc(0, this.getHeight()/4, 8, 8, 0, 360);
@Override
public void setStatus (final int status)
this.status = status;
if (status !=0)
repaint(); // Doesn't work :(
private Color getColor ()
switch (status)
case FTPConnectionListenable.STATUS_OK:
return Color.GREEN;
case FTPConnectionListenable.STATUS_WARNING:
return Color.ORANGE;
case FTPConnectionListenable.STATUS_ERROR:
return Color.RED;
default:
return Color.PINK;
【问题讨论】:
我强烈建议您使用enum
而不是interface
来代替FTPConnectionListenable
。
【参考方案1】:
Klong,你的代码对我有用,所以很可能你在其他地方有错误。我是如何测试它的,
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
class StatusLabel extends JLabel implements FTPConnectionListenable
private Integer status;
// Constructor
StatusLabel(final String text)
super(text);
setFont(new Font("Dialog", Font.PLAIN, 10));
setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
@Override
public void paintComponent(final Graphics g)
super.paintComponent(g);
g.setColor(getColor());
g.fillArc(0, this.getHeight()/4, 8, 8, 0, 360);
@Override
public void setStatus (final int status)
this.status = status;
if (status !=0)
repaint();
private Color getColor ()
switch (status)
case FTPConnectionListenable.STATUS_OK:
return Color.GREEN;
case FTPConnectionListenable.STATUS_WARNING:
return Color.ORANGE;
case FTPConnectionListenable.STATUS_ERROR:
return Color.RED;
default:
return Color.PINK;
public static void main(String[] args)
final StatusLabel statusLabel = new StatusLabel("Foo");
statusLabel.setStatus(FTPConnectionListenable.STATUS_OK);
new Timer(1000, new ActionListener()
int counter = 0;
@Override
public void actionPerformed(ActionEvent e)
counter++;
counter %= 4;
statusLabel.setStatus(counter);
).start();
JOptionPane.showMessageDialog(null, statusLabel);
interface FTPConnectionListenable
static final int STATUS_ERROR = 0;
static final int STATUS_WARNING = 1;
static final int STATUS_OK = 2;
void setStatus(int status);
顺便说一句,这是一个小弧线。
【讨论】:
【参考方案2】:你应该在做任何事情之前重写paintComponent并调用super方法:
@Override
public void paintComponent(Graphics g)
super.paintComponent(g);
g.setColor(getColor());
g.fillArc(0, this.getHeight()/4, 8, 8, 0, 360);
【讨论】:
@klong:“但它不起作用”什么也没告诉我们。当你尝试它时会发生什么?错误?没有显示?会后空翻吗? @Heisenburg 显式调用 repaint() 的原因是使用新的 status 值执行 paintComponent 方法。不起作用的是圆圈不会改变颜色。我可以强制paintComponent以新状态执行的唯一方法是调整屏幕大小。 @klonq:对不起..我没有看到那个方法。让我想想可能是什么问题。 @klong,你在别处遇到了一个错误,因为你的代码对我来说很好。 @klong: 检查状态值是否有效地不同于 0【参考方案3】:我注意到的第一件事是您应该覆盖paintComponent
,而不是paint
。
【讨论】:
@klonq,当我有更多时间时,我会仔细看看这个。感谢您的反馈。【参考方案4】:如果它没有重新绘制,那么问题可能是您在事件调度线程上进行 FTP 连接,该线程阻塞并阻止 GUI 重新绘制。
您需要为 FTP 连接使用单独的线程。阅读 Concurrency 上的 Swing 教程部分,了解更多信息和使用 SwingWorker
的解决方案。
【讨论】:
【参考方案5】:您可能只想覆盖paintComponent()
,而不是覆盖paint()
。
另外,对super.paint(g)
的调用应该在你的方法开始时完成,否则你执行的任何绘画都可能被JLabel
自己的绘画覆盖。
【讨论】:
【参考方案6】:状态需要是可变的,以确保事件调度线程看到 ftp 线程设置的新值。
【讨论】:
以上是关于Swing JLabel:强制重绘()的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Java Swing 中的 JLabel 中设置行距/高度?