Reputation: 1575
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?
Upvotes: 3
Views: 851
Reputation: 36423
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
}
paintComponent()
declare your Image
globally, assign it in the constructor and then use it in paintComponent()
. F.irather 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);
}
}
}
Upvotes: 5
Reputation: 109815
Do not load image or another hard or long running code in paintComponent
Load this Object
as a local variable and only one time
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
.
If there is animation, then to use Swing Timer and call repaint()
.
Upvotes: 5