重画不被召唤

时间:2012-10-02 14:22:59

标签: java swing repaint paintcomponent event-dispatch-thread

您好我已经google了,无法弄清楚为什么我的paintComp方法不被称为

我有以下代码 包com.vf.zepto.view;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.vf.zepto.view.interfaces.ProcessorPanel;

public class CountryDetailsPanel extends JPanel implements ProcessorPanel, Runnable {
    private GridBagConstraints c = new GridBagConstraints();
    private String countryName;
    private Properties prop = new Properties();
    private BufferedImage image;

    public CountryDetailsPanel() {
        try {
            prop.load(new FileInputStream("country.props"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        //this.setLayout(new GridBagLayout());

        c.gridx = 0;
        c.gridy = 0;
        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(5, 5, 5, 5);

        this.setPreferredSize(new Dimension(200, 200));
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        try {
            if(countryName != null) {
                String asset = prop.getProperty(countryName+".flag");

                if(!asset.equals(null)) {
                    image = ImageIO.read(new File(asset));
                    g.drawImage(image, 0, 0, null);
                }
            }
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void updateDetails(Object o) {
        countryName = (String)o;
        SwingUtilities.invokeLater(this);
    }

    @Override
    public void run() {
        this.repaint();
    }
}

并且在调用this.repaint()期望调用paintComponent方法时,但是为了爱情和金钱,它不是。

试图强迫它使用EDT incase是问题,但事实并非如此。

任何想法?

2 个答案:

答案 0 :(得分:5)

  1. paintComponent

  2. 加载图片或其他难以运行的代码
  3. 将此Object加载为本地变量且只加载一次

  4. paintComponent()被称为

    • 隐含地,当JComponent需要重绘时,或

    • 显式地,例如,如果要从paintComponent()调用MouseMotionListener,则在每个鼠标事件上。

  5. 如果有动画,则使用Swing Timer并调用repaint()

答案 1 :(得分:5)

  • 您永远不应该调用paintComponent() repaint()方法合并所有更改组件的请求(屏幕刷新之间可能有多次重新绘制请求)。它向GUI事件队列添加更新请求,以便更新将与其他GUI操作正确协调(Swing和AWT不是线程安全的)。此更新请求在处理后会调用update(),调用paint(),调用paintComponent()

  • 为什么会这样:

    @Override
    public void run() {
        this.repaint();
       }
    

它似乎没有任何用处(创建一个新线程重绘一次?更不用说线程不在EDT上而是在repaint()实例上调用JPanel(如果在外部修改除此之外)你甚至不用担心。)但是要开始一个modifeis UI组件使用s SwingTimer / SwingWorkerSwingUtilities#invokeXXX()

的线程
  • 这可能没有关系,但在您的代码中我看到了:

            if(!asset.equals(null)) {
                image = ImageIO.read(new File(asset));
                g.drawImage(image, 0, 0, null);
            }
    

请勿使用equals()null值进行比较,因为这可能会导致NullPointerException因为您正在尝试 deference一个空指针,例如这段代码抛出NPE

    String s=null;
    if(!s.equals(null)) {//throws NPE
        System.out.println("Here");//is never printed
    }
  • 同样正如mKorbel所说(+1给他)不要在paintComponent()中执行长时间运行的任务,在全局范围内声明你的Image,在构造函数中指定它,然后在paintComponent()中使用它。 F.i

而是:

public class TestPanel extends JPanel {

private Image image;

public TestPanel() {
image = ImageIO.read(new File(asset));
}

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
                if(asset!=null) {
                    g.drawImage(image, 0, 0, null);
                }
    }
}