Question

Hi I have googled and can't figured out why my paintComp method isnt being called

I have the following code package 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();
    }
}

and when calling this.repaint() expect the paintComponent method to be called but for love nor money it isnt.

Have tried to force it to use the EDT incase that was the issue but its not.

any ideas?

Was it helpful?

Solution

  • You should never call paintComponent() the repaint() method consolidates all requests to change the component (there may be several repaint requests between screen refreshes). It adds an update request to the GUI event queue so that the update will be properly coordinated with other GUI actions (Swing and AWT are not thread-safe). This update request, when processed, calls update(), which calls paint(), which calls your paintComponent()

  • Why have this:

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

It does not seem of any use (creating a new thread to repaint once? Not to mention the thread is not on EDT rather call repaint() on the JPanel instance (if modified externally other than that you shouldnt even worry). However to start a thread which modifeis UI componets use s SwingTimer/SwingWorker or SwingUtilities#invokeXXX()

  • This might not be related but in your code I see this:

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

dont use equals() to compare to a null value as this might throw a NullPointerException because you are attempting to deference a null pointer, for example this code throws a NPE:

    String s=null;
    if(!s.equals(null)) {//throws NPE
        System.out.println("Here");//is never printed
    }
  • Also as mKorbel has said (+1 to him) dont do long running tasks in paintComponent() declare your Image globally, assign it in the constructor and then use it in paintComponent(). F.i

rather do:

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

OTHER TIPS

  1. Do not load image or another hard or long running code in paintComponent

  2. Load this Object as a local variable and only one time

  3. paintComponent() is called

    • implicitly, when JComponent requires repaint, or

    • explicitly, for example on every of mouse event if one were to invoke paintComponent() from a MouseMotionListener.

  4. If there is animation, then to use Swing Timer and call repaint().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top