Swing JLabel:强制重绘()

时间:2011-09-13 14:50:29

标签: java swing components repaint

我正在尝试动态重新绘制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;
        }
    }
}

6 个答案:

答案 0 :(得分:4)

Klong,你的代码适合我,所以你可能在其他地方有一个bug。我是如何测试的,

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);

}

顺便说一下,这是一个弧。

答案 1 :(得分:3)

在执行任何其他操作之前,您应该覆盖paintComponent并调用super方法:

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(getColor());
    g.fillArc(0, this.getHeight()/4, 8, 8, 0, 360);

}

答案 2 :(得分:2)

我注意到的第一件事是你应该覆盖paintComponent,而不是paint

答案 3 :(得分:2)

您可能只想覆盖paint(),而不是覆盖paintComponent()

此外,对super.paint(g)的调用应在方法的开头进行,否则您执行的任何绘画都可能被JLabel自己的绘画覆盖。

答案 4 :(得分:2)

如果它没有重新绘制,则问题很可能是您在事件调度线程上进行了FTP连接,该线程阻塞并阻止GUI重新绘制。

您需要为FTP连接使用单独的线程。阅读Concurrency上的Swing教程中的部分,了解更多信息以及使用SwingWorker的解决方案。

答案 5 :(得分:0)

状态需要是volatile才能确保Event Dispatch Thread看到ftp线程设置的新值。