如何强制调用paintComponent?

时间:2013-11-25 18:59:21

标签: java swing icons jlabel paintcomponent

我有一个带有paintComponent()覆盖的JLabel。我希望它被强制调用,因为更新我的Label UI的代码就是这个事件。我如何强制调用和更新UI? (顺便说一句,重画不起作用!)

这是我的代码:

BufferedImage background;
String Uri;

public CustomClockLabel(String Uri){
    init(Uri);
    this.Uri = Uri;
}

public void init(String Uri){
    try {
        URL inp = CustomClockLabel.class.getResource(Uri);
        background = ImageIO.read(inp);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
protected void paintComponent(Graphics g){
    Graphics2D g2 = (Graphics2D) g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    if(background != null){
        g2.drawImage(background, 0, 0,getWidth(),getHeight(), this);
    }
    g2.dispose();
    super.paintComponent(g);
}

这是更新标签的代码,它是递归调用的:

lblHour1 = new CustomClockLabel("/icons/noa_en/"+Hour.charAt(0)+".png");
lblHour1.repaint();
lblHour2 = new CustomClockLabel("/icons/noa_en/"+Hour.charAt(1)+".png");
lblHour2.repaint();
lblMin1 = new CustomClockLabel("/icons/noa_en/"+Minute.charAt(0)+".png");
lblMin1.repaint();
lblMin2 = new CustomClockLabel("/icons/noa_en/"+Minute.charAt(1)+".png");
lblMin1.repaint();

4 个答案:

答案 0 :(得分:2)

在相关组件上调用repaint()将强制它再次绘制。

您遇到的问题似乎没有重新绘制,因为您实际上正在更改面板上的标签。确保删除旧标签并添加新标签并致电revalidate()。 (您发布的代码看起来就像是更新标签引用而不是实际在面板上更改它们。)

总的来说,通过让CustomClockLabel类接受一个更改图像的参数,可以显着改善设计,因此可以调用repaint()。

答案 1 :(得分:2)

lblHour1 = new CustomClockLabel("/icons/noa_en/"+Hour.charAt(0)+".png");

上面的代码没有做任何事情。一切都是创造一个新的组件。但该组件未添加到GUI中,因此显然不会重新绘制。

你班上没有任何东西会导致它需要重新粉刷,所以你的问题没有意义。你有一个设计问题。我认为没有理由创建自定义标签。

如果要更改图像,只需使用带有图标的标准JLabel即可。然后要更改图像,只需使用setIcon(...)方法,标签将自动重新绘制。

答案 2 :(得分:2)

  

(顺便说一句,重画不起作用!)

如果不是,那么我唯一可以怀疑的是,错误在于你的绘画顺序:在你绘制图像后你在哪里打电话super.paintComponent(g);。如果您的标签是非透明的并且具有背景颜色,那么您将看不到图像,因为后面的绘画super.paintComponent(g)将被绘制在上一幅画的上方。

尝试更改订单:

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

if(background != null){
    g2.drawImage(background, 0, 0,getWidth(),getHeight(), this);
}
g2.dispose();

答案 3 :(得分:2)

您可能会误以为创建新标签会更新屏幕上的内容,这样做......

lblHour1 = new CustomClockLabel("/icons/noa_en/"+Hour.charAt(0)+".png");
lblHour2 = new CustomClockLabel("/icons/noa_en/"+Hour.charAt(1)+".png");
lblMin1 = new CustomClockLabel("/icons/noa_en/"+Minute.charAt(0)+".png");
lblMin2 = new CustomClockLabel("/icons/noa_en/"+Minute.charAt(1)+".png");

将更改变量的引用,因此它们将不再是您添加到屏幕的变量。

假设已经将上述变量添加到屏幕上,您只需使用类似的内容即可更新它们。

lblHour1.init(new ImageIcon("/icons/noa_en/"+Hour.charAt(0)+".png"));
lblHour2.init(new ImageIcon("/icons/noa_en/"+Hour.charAt(1)+".png"));
lblMin1.init(new ImageIcon("/icons/noa_en/"+Minute.charAt(0)+".png"));
lblMin2.init(new ImageIcon("/icons/noa_en/"+Minute.charAt(1)+".png"));
revalidate();
repaint();

如果失败,你应该尝试设置一个标签边框的属性,这样你就可以看到它是否真的被添加到了屏幕上。

<强>更新

经过一些实验,你所提供的代码很少,这里有更多的建议......

  1. 正如已经提到的那样,请确保首先调用super.paintComponent,因为此方法的任务之一是清除可以绘画的图形......
  2. 确保为组件提供合适的大小提示,因此布局管理器可以对组件的大小有所了解。这可确保组件的大小不会0x0
  3. 以下示例非常简单,但是您提供的代码很少,并且从中构建了一个可运行的示例......

    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class PaintComponentTest {
    
        public static void main(String[] args) {
            new PaintComponentTest();
        }
    
        private int time = 0;
    
        public PaintComponentTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    final CustomClockLabel counter = new CustomClockLabel("/icons/0.png");
                    Timer timer = new Timer(1000, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            time++;
                            if (time > 9) {
                                time = 0;
                            }
                            counter.init("/icons/" + Integer.toString(time) + ".png");
                            counter.repaint();
                        }
                    });
                    timer.start();
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(counter);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class CustomClockLabel extends JPanel {
    
            BufferedImage background;
            String Uri;
    
            public CustomClockLabel(String Uri) {
                init(Uri);
                this.Uri = Uri;
            }
    
            public void init(String Uri) {
                try {
                    URL inp = getClass().getResource(Uri);
                    background = ImageIO.read(inp);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(100, 100);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
                if (background != null) {
                    g2.drawImage(background, 0, 0, getWidth(), getHeight(), this);
                }
                g2.dispose();
            }
        }
    
    }