user2458087
user2458087

Reputation: 21

Images in paintComponent only show up after resizing the window

I want to use paintComponent(Graphics g) to paint a few images using a for loop. However, the JFrame just shows up as a white screen, and it only shows the black background and the images after I resize the window.

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*;
import java.io.*; 
import javax.imageio.*; 
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.awt.Graphics;
import java.util.Scanner;

 public class SimpleAdventure {
         private JFrame frame;
         private CardLayout cards;
         private Container c;
         private DrawPanel1 gamepanel;
         private BufferedImage greentiles, pinktiles, sandtiles, charsprites;
         private Image left1, right1, left2, right2, front;
         private Image pinkbg, greenbg, sandbg;
         private Image pinktop, greentop, sandtop;
         private int charx, chary;

         public SimpleAdventure()
         {}
         public static void main (String [] args)
         {
                 SimpleAdventure retro = new SimpleAdventure();
                 retro.run();
         }
         public void run()
         {
                 frame = new JFrame("Simple Adventure");
                 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                 frame.setSize(576, 576);
                 frame.setVisible(true);
                 // frame.setResizable(false);
                 getImage();


                 c = frame.getContentPane();
                 cards = new CardLayout();
                 c.setLayout(cards);

                 gamepanel = new DrawPanel1();
                 gamepanel.setBackground(Color.black);
                 c.add(gamepanel, "Panel 1");
         }
         public void getImage()
         {

             try
             {
                 greentiles = ImageIO.read(new File("greenTiles.png"));
                 pinktiles = ImageIO.read(new File("pinkTiles.png"));
                 sandtiles = ImageIO.read(new File("sandTiles.png"));
                 charsprites = ImageIO.read(new File("charactersheet.png"));
             }
             catch(IOException e)
             {
                 e.printStackTrace();
             }


             left1 = charsprites.getSubimage(18, 0, 6, 6);
             left2 = charsprites.getSubimage(24, 0, 6, 6);
             right1 = charsprites.getSubimage(0, 0, 6, 6);
             right2 = charsprites.getSubimage(6, 0, 6, 6);
             front = charsprites.getSubimage(12, 0, 6, 6);

             greenbg = greentiles.getSubimage(240, 0, 16, 16);
             sandbg = sandtiles.getSubimage(240, 0, 16, 16);
             pinkbg = pinktiles.getSubimage(240, 0, 16, 16);

             greentop = greentiles.getSubimage(224, 0, 16, 16);
             sandtop = sandtiles.getSubimage(224, 0, 16, 16);
             pinktop = pinktiles.getSubimage(224, 0, 16, 16);
         }

         class DrawPanel1 extends JPanel implements KeyListener
         {
                 // private BottomPanel lower;
                 public DrawPanel1()
                 {
                     /*this.setLayout(new BorderLayout());
                     lower = new BottomPanel();
                     this.add(lower, BorderLayout.SOUTH);*/
                     addKeyListener(this);
                 }

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

                         for(int i = 0; i < 7; i++)
                         {
                             g.drawImage(greentop, 0 + (i * 96), 480, 96, 96, this);
                         }
                         System.out.println("check");
                 }
                 public void keyPressed(KeyEvent e)
                 {

                 }
                 public void keyReleased(KeyEvent e)
                 {

                 }
                 public void keyTyped(KeyEvent e)
                 {

                 }
         } }

Upvotes: 1

Views: 2982

Answers (2)

Cameron Skinner
Cameron Skinner

Reputation: 54356

You need to call frame.pack() to do the initial layout. Resizing the window automatically causes the layout to be fixed, but frame.setSize(...) does not*.

Move frame.setVisible(true) to the end of your run method (i.e. after you've constructed all the UI elements) and put frame.pack() just before frame.setVisible(true). (Thanks Hovercraft and MadProgrammer for pointing this out)

*At least, it doesn't if the frame is not visible. It might work if the frame is already visible; try it and see.

EDIT: Now that I re-read the javadoc, you probably don't want pack after all - it will resize the frame for you. Without testing it, I guess that moving setVisible to the end will work; if it doesn't then use revalidate rather than pack to get the layout engine to run.

EDIT 2: Now that I re-re-read the javadoc, setVisible will validate the window if it is not already displayable. So you won't need an explicit call to revalidate. setSize will invalidate the component but will not revalidate it.

TL;DR: It's worth reading up on how validation and displayability work in Swing so you don't make the mistakes I just did.

Upvotes: 5

MadProgrammer
MadProgrammer

Reputation: 347314

Call setVisible only after you have built the UI...

public void run()
{
    frame = new JFrame("Simple Adventure");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(576, 576);
    // frame.setResizable(false);
    getImage();


    c = frame.getContentPane();
    cards = new CardLayout();
    c.setLayout(cards);

    gamepanel = new DrawPanel1();
    gamepanel.setBackground(Color.black);
    c.add(gamepanel, "Panel 1");

    // Lucky last...   
    frame.setVisible(true);
}

Otherwise you will need to revalidate the frame

Upvotes: 3

Related Questions