1

I'm trying to design a GUI using SWING.My problem is that I'm not sure how the paintComponent method works. I'm trying to display 2 images but only the one from PanClass is displayed.Here is the relevant code(2 classes) .

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.Image;

public class LP3 extends JPanel
{
    public static BufferedImage image;
    public static BufferedImage image2;
    private JFrame frame=new JFrame();
    private PanClass Panel=new PanClass();

    public LP3()
    {
        try
        {               
            image2=ImageIO.read(new File("New Game.png"));     
        }
        catch (IOException e)
        {
            //Nothing
        }
        frame.setSize(1000,100);
        frame.setResizable(true);
        frame.add(Panel);
        Panel.setOpaque(true);
        frame.pack();
        frame.setVisible(true);     
    }

    public void paintComponent(Graphics g)
    {
        g.drawImage(image2,0,0,null);
    }
}

Class No2:

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.Image;

public class PanClass extends JPanel
{
    private static BufferedImage theimage;
    private static BufferedImage image2;
    private JPanel a=new JPanel();

    public PanClass()
    {
        a.setLayout(null);
        a.setOpaque(true);
        try
        {                 
            theimage = ImageIO.read(new File(design4.jpg"));
        }
        catch (IOException e)
        {
            //Not handled.
        }
    }

    public void paintComponent(Graphics g)
    {
        g.drawImage(theimage,0,0,null);
    }
}

The code as it is now displays only the image from PanClass. If I get to add the drawing of both images to be done in the PanClass then both will be correctly drawn. I am interested in knowing why this happens as I'm more interested in learning how it works rather than getting the job done. Also If I create a JFrame and a JLayered Pane in a class, then create 2 more classes drawing an image with paintComponent() (using similar code to the above) and then add an instance of each class on the Layered Pane on a different Layer of the first class, why nothing is displayed?

(My main method is supposed to be on LP3 but I'm just using an IDE that allows you to call methods directly on instances without having a main method-used for learning)

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Anon855
  • 17
  • 4
  • 2
    1) A single blank line of white space in source code is *always* enough. 2) Change code of the form `catch (Exception e) { ..` to `catch (Exception e) { e.printStackTrace(); // very informative! ..` 3) Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components. To organize the components for a robust GUI, instead use layout managers, or combinations of them, along with layout padding & borders for white space. .. – Andrew Thompson Jun 24 '13 at 14:07
  • 1
    .. 4) Use a consistent and logical indent for code blocks. The indentation of the code is intended to help people understand the program flow. 5) For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Jun 24 '13 at 14:07
  • why are you trying to add a frame to the panel? And you are not even adding it at that? – Oliver Watkins Jun 24 '13 at 14:08
  • Where am I doing that? – Anon855 Jun 24 '13 at 15:55

2 Answers2

3

You didn't add LP3 to the JFrame but only PanClass was added. So the LP3's paintComponent() is not called.

You can add both component (may be define proper LayoutManager e.g. GridLayout) to call both paintComponent()

nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • Thanks for replying. I'm not sure what you mean. Isn't it going to be an infinite loop if I add instances of LP on the JFrame?(My main method is supposed to be on LP3 but I'm just using an IDE that allows you to call methods directly on instances without having a main method-used for learning) – Anon855 Jun 24 '13 at 14:02
  • your Frame should be the first thing that is created. All the panels should be lower down in the hierarchy. why not have LP3 extends JFrame? – Oliver Watkins Jun 24 '13 at 14:10
  • I'm not sure why I get this behavior. I don't understand why paintComponent is not called in the LP3 class. Shouldn't it be called automatically? – Anon855 Jun 24 '13 at 15:59
1

Points you doing wrong in your program :

  • Naming Conventions used by you in your code, does not implies with Java. Please do refer to Java Naming Conventions for more info. Two easy things use Pascal Notions for Class Names and Camel notation for Variable Names.
  • Whenever one needs to override the method of the super class, it is BEST to keep the ACCESS SPECIFIER, the same, as much as possible. In your case, the Access Specifier for the paintComponent(...) method is protected and not public.
  • Especially while overriding paintComponent(...), it is BEST to call super.paintComponent(...), in the overridden method.
  • Inside your PanClass which extends JPanel you are creating a new JPanel a, which is not what you want, if you look closely. You want PanClass itself.
  • Make it a customary habit to override, the getPreferredSize(), of the JPanel/JComponent, when ever you are extending it to any class.
  • Always define the behaviour how the JFrame needs to go off, when the X Button is pressed. For more Info JFrame.setDefaultCloseOperation(...)
  • Whenever overriding a method of super class, its best to prefix it with an Annotations. More information on Java Annotation Tutorials
  • I hope after everything, a small information related to Concurrency in Swing, is worth mentioning :-)
  • Last but not the least, the answer is very much given by @StanislavL

Please consider this code for more reference :

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.awt.Image;
import java.net.URL;

public class LP3 extends JPanel
{
    public static BufferedImage image;
    public static BufferedImage image2;
    private JFrame frame = new JFrame();
    private PanClass panel = new PanClass();

    public LP3()
    {
        setOpaque(true);
        try
        {               
            image2=ImageIO.read(new URL(
                "https://encrypted-tbn1.gstatic.com/images?q=tbn:" + 
                "ANd9GcQCluuYpyVQYZuADHAYIfpkRO7SaWMn0OCM_nGH6Tr2SCFtGtE_"));     
        }
        catch (IOException e)
        {
            //Nothing
            e.printStackTrace();
        }           
    }

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(300, 300));
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.drawImage(image2,0,0,this);
    }

    private void displayGUI()
    {
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setResizable(true);
        JPanel contentPane = new JPanel();
        contentPane.setLayout(new GridLayout(0, 1, 5, 5));
        contentPane.add(panel);
        contentPane.add(this);
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setVisible(true); 
    }

    public static void main(String[] args)
    {
        Runnable runnable = new Runnable()
        {
            @Override
            public void run()
            {
                new LP3().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

class PanClass extends JPanel
{
    private static BufferedImage theimage;
    private static BufferedImage image2;

    public PanClass()
    {
        setOpaque(true);
        try
        {                 
            theimage = ImageIO.read(
                new URL(
                    "https://encrypted-tbn0.gstatic.com/" + 
                    "images?q=tbn:ANd9GcR5PNwAcLVjphhST_" + 
                    "S-K_dU0CEAuXM0g4oc1-v1r-z5VJFuemOD"));
        }
        catch (IOException e)
        {
            //Not handled.
            e.printStackTrace();
        }
    }

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(300, 300));
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.drawImage(theimage, 0, 0, this);
    }
}

EDIT : !

  • I forgot one very important point the previous time regarding your use of g.draw(...), you using null for the ImageObserver part, which in this case is your JPanel and not null
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
  • Good points, but I'm curious why you're recommending overriding `getPreferredSize`. Can you explain a bit more about why this is a good idea ? – Radu Murzea Jun 24 '13 at 16:53
  • @RaduMurzea : Actually, as stated in [this post](http://stackoverflow.com/q/7229226/1057230), one should restrict oneself from using methods like `setXxX()` methods. Overriding `getPreferredSize()` explicitly makes life a bit more easier for the `Layout Manager` to calculate the size for the `Component`, for drawing the said `Component` for `View`. If you look closely, [Java Tutorials](http://docs.oracle.com/javase/tutorial/uiswing/painting/step2.html) itself prefer it many a times. For the rest Thankyou and KEEP SMILING :-) – nIcE cOw Jun 24 '13 at 16:59
  • @nIcE cOw: Thank you very much. I see my mistakes and now I understand. I have one more question though. Above it is said that using a Layout Manager should always be preferred. If you are to design a game interface exactly how you want it, would a LayoutManager be flexible enough? – Anon855 Jun 24 '13 at 17:07
  • @Anon855 : Actually it depends on __ONE's__ requirement. Mostly `Layout Managers` are flexible enough, if not from `Java Domain`, then third party `Layout Managers` do come in handy (example of few will be [MigLayout](http://www.miglayout.com/), [JGoodies FormLayout](http://www.jgoodies.com/freeware/libraries/forms/)) and many more (some of them are written by @camickr, [DragLayout](http://tips4java.wordpress.com/2011/10/23/drag-layout/)). Though if your needs demand creating objects at random locations, then yeah one has to use `Absolute Positioning`, though always resort to that at the – nIcE cOw Jun 24 '13 at 17:14
  • @Anon855 : __continued...__ very end. Do try to use them as much as one can before drifting to the worse case scenario :-). For the rest You're MOST WELCOME and KEEP SMILING :-) – nIcE cOw Jun 24 '13 at 17:15