Java Swing JLabel:强制重新绘制()

Java Swing JLabel:强制重新绘制(),java,swing,components,repaint,Java,Swing,Components,Repaint,我正在尝试动态地重新绘制一个JLabel,但我一辈子都不知道该怎么做。一旦我调整屏幕大小,下面的代码将按预期执行,但不会自行执行代码 JLabel左侧有一个小圆圈,在文本左侧的边界区域中绘制。圆圈的颜色应随FTP连接的运行状况而变化(未显示)。当运行状况发生变化时,监视FTP连接的线程调用setStatus(int)方法 圆圈是在JLabel初始化期间绘制的,我正在尝试使用repaint()重新执行此代码 编辑:我也尝试过玩revalidate(),invalidate(),和validate(

我正在尝试动态地重新绘制一个JLabel,但我一辈子都不知道该怎么做。一旦我调整屏幕大小,下面的代码将按预期执行,但不会自行执行代码

JLabel左侧有一个小圆圈,在文本左侧的边界区域中绘制。圆圈的颜色应随FTP连接的运行状况而变化(未显示)。当运行状况发生变化时,监视FTP连接的线程调用
setStatus(int)
方法

圆圈是在JLabel初始化期间绘制的,我正在尝试使用
repaint()
重新执行此代码

编辑:我也尝试过玩
revalidate()
invalidate()
,和
validate()
,但都没有用

编辑:感谢您指出这一点,我从使用
paintComponent()
开始,并在不起作用时改为
paint()
。所以,作为回答给出这个答案并没有什么荣耀(对不起,向神谕者提出这个问题)


我注意到的第一件事是您应该重写
paintComponent
,而不是
paint

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

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

}

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


另外,对
super.paint(g)
的调用应该在方法开始时完成,否则您执行的任何绘制都可能被
JLabel
自己的绘制覆盖。

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

}

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

如果它没有重新绘制,那么问题很可能是您正在事件调度线程上进行FTP连接,这会阻止GUI重新绘制


FTP连接需要使用单独的线程。阅读Swing教程中关于的部分以了解更多信息,使用
SwingWorker

状态的解决方案需要易变,以确保事件调度线程看到ftp线程设置的新值。

@klong:“但它不起作用”没有告诉我们任何信息。当你尝试时会发生什么?错误?没有显示?它是否会反向翻转?@Heisenburg显式调用repaint()的原因是使用新的status值执行paintComponent方法。不起作用的是圆圈不改变颜色。我可以强制paintComponent以新状态执行的唯一方法是调整屏幕大小。@klonq:对不起。。我没有看到那种方法。让我想一想可能是什么问题。@klong,您在其他地方有一个bug,因为您的代码对我来说运行良好。@klong:检查状态值是否与0@klonq,等我有更多的时间,我会仔细看看这个。感谢您的反馈。对于
FTPConnectionListenable
,我强烈建议您使用
enum
而不是
接口。
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);

}