1

I tried to override method paintComponent in inner class JPanel and paint some picture. But if I load image in the constructor, method paintComponent is not calling. If load image in main class, everythig is fine. What is it? Here's the code, that does'nt work

import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {
JFrame window;
//Image image=new ImageIcon("D://domik.png").getImage();

class JPanelExt extends JPanel {
    Image image;

    public JPanelExt (){            
    image=new ImageIcon("D://domik.png").getImage();
    System.out.println("constructor");          
    }

    @Override
    public void paintComponent(Graphics g) {            
        super.paintComponent(g);
        System.out.println("paint");
        g.drawImage(image, 0, 0, this);
        g.drawRect(0, 400, 100, 100);       
    }   
}       

public Main(){

    window=new JFrame("Flowers");
    window.setSize(430, 480);
    window.setVisible(true);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                      
    JPanelExt flower1 =new JPanelExt();
    flower1.setBounds(100, 100, 200, 200);
    flower1.setToolTipText("House");                
    window.setLayout(null);             
    window.add(flower1);                
}   
public static void main(String[] args) {

    Main main=new Main();       
}
}

And sysout writes only "constructor"

But if I change code this way

public class Main {
JFrame window;
Image image=new ImageIcon("D://domik.png").getImage();

class JPanelExt extends JPanel {
    //Image image;

    public JPanelExt (){

    //image=new ImageIcon("D://domik.png").getImage();
    System.out.println("constructor");
             }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        System.out.println("paint");
        g.drawImage(image, 0, 0, this);
        g.drawRect(0, 400, 100, 100);

    }

And sysout writes "constructor","paint"

I can't understand this ))

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Start by calling `setVisible` on your frame last - and make use of an appropriate layout manager – MadProgrammer Jul 17 '13 at 06:21
  • 1
    You should also check out [Initial Threads](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) – MadProgrammer Jul 17 '13 at 06:33
  • Moreover, instead of providing `Absolute Path`, please refer to this [answer](http://stackoverflow.com/a/11372350/1057230), for adding images to the application. – nIcE cOw Jul 17 '13 at 06:39

1 Answers1

3

Your "problem" is the order of statements in the Main constructor.

First you are constructing a new frame. Second, you set it visible. At this point it is painted and also calls the paint methods on its associated panels. Also at this point, there is no associated panel. Third, you construct a new JPanelExt and add it to the frame. This will not cause the frame to be repainted.

Put the call

window.setVisible(true);

at the end of the construction process. Then you will see your image.

Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/), is also the need of the hour, which also needs to be given weightage, i.e. putting everything inside main method like this `EventQueue.invokeLater(new Runnable(){ public void run(){/*Here goes the content of main*/}});`, along with the present info, +1 – nIcE cOw Jul 17 '13 at 06:35
  • Thanks a lot! But why the second variant works and call paintComponent? – user2588825 Jul 17 '13 at 06:38
  • @user2588825 : Because, your `window` was already visible, before you even added the `flower1` to it, hence the `repaint()` call will only happen, IMHO, when you will minimize your window, or drag to `inc/dec` it's size. THat is why its considered a good practice, to first add all components to the parent container, and then make it visible and not before that :-) – nIcE cOw Jul 17 '13 at 06:41
  • @user2588825 : If the previous approach never works out then, I guess, in its present form you have to call `flower1.revalidate() and flower1.repaint()` as the last lines of your main method... – nIcE cOw Jul 17 '13 at 09:03