Search code examples
javaswinggraphicsgraphics2d

Need help in clearing certain doubts in my swing app


Below is a simple swing app in which i was experimenting certain custom techniques.The code is as follows :-

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class ThemeComponents extends JFrame{
  public static void main(String args[])
  {
    SwingUtilities.invokeLater(new Runnable(){public void run(){new    ThemeComponents();}});
  }

  public ThemeComponents()
  {
    super("HACK 1:Creating Image Themed Components ");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(new FlowLayout());
    CustomPanel p1=new CustomPanel();
    p1.add(new CustomLabel());
    add(p1);
    pack();
    setVisible(true);
  }
}

class CustomPanel extends JPanel
{
  BufferedImage img;
  CustomPanel()
  {
    try
    {
      img=ImageIO.read(new File("src/background.jpg"));
    } catch(IOException e){
      System.out.println("Error in loading background image "+e);
    }
  }
  public void paintComponent(Graphics g)
  {
    g.drawImage(img,0,0,getWidth(),getHeight(),null);
  }
  public Dimension getPreferredSize()
  {
    return new Dimension(img.getWidth(),img.getHeight());
  }
}

class CustomLabel extends JLabel
{
  ImageIcon img;
  CustomLabel ()
  {
    img=new ImageIcon("src/tornado.gif");


    setSize(img.getIconWidth(),getHeight());
    setIcon((Icon) img);
    //setOpaque(false);
    //setIconTextGap(0);
    setLocation(10,10);
  }
}

Now I have following questions :-

1)When i set the layout to null setLayout(null) in my main class ThemeComponents then why the frame size shrinks to null with only title bar ?I expected it to take the size of CustomPanel as i have used pack() for the frame.(using layouts such as flowlayout , borderlayout however produces correct output)

2)Is using getPreferredSize() better for setting the size of component instead of setPreferredSize().Actually i don't find any difference between them.


Solution

    1. If you use null-layout, preferred size will return (0,0) and hence you will only see the title bar. pack() validates your JFrame and then sets the size of the JFrame to the preferred size of the content pane (which is 0,0) and add the required space for the title bar, menus, etc...

    2. Most likely you should avoid calling setPreferredSize() and rather override getPreferredSize(). Calling setPreferredSize() leaves the possibility to others to modify that value. In such situation it probably means that the preferred size is not an intrinsic part of your component and therefore you should not need to call setPreferredSize(). While overriding getPreferredSize() gives you full control and results in the preferred size being an intrinsic part of your component.

    3. You should also call super.paintComponent(g); in your CustomPanel.

    4. In your CustomLabel, it does not make any sense to call setLocation (the parent layout will change that anyway)

    5. In your CustomLabel, this does not make any sense either: setSize(img.getIconWidth(),getHeight()); since the parent layout will change those values anyway (and btw, getHeight() returns 0 in this case)