4

I have a JFrame. In that i have used:

  1. JTabbed panes.
  2. JButton.
  3. background images in a Jlabel which is added in JPanel.
  4. Nimbus look and feel.

My problem is that whenever i use Nimbus look and feel the JButton vanishes only if there is a background image added. But this doesn't happen with other look and feel. Can anyone help me in getting the button visible?

Here is my code:

import javax.swing.ImageIcon;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JFrame; 
import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;

import java.awt.*;
import java.awt.event.*;

class ImageTest 
{
JTabbedPane tp;
JLabel lab1;
JPanel  welcome;
JFrame frame;
ImageIcon image2;
JButton b1;
public void createUI()
{
    frame=new JFrame("JTabbedPane Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    b1=new JButton();
    welcome= new JPanel(null);
    welcome.setPreferredSize(new Dimension(1366,786));
    ImageIcon icon = new ImageIcon(ImageTest.class.getResource("icloud.jpg"));

    tp=new JTabbedPane();
            Container pane = frame.getContentPane();
    pane.add(tp);
    tp.addTab("Welcome", welcome);
            lab1=new JLabel();
    lab1.setIcon(icon);

    b1.setBounds(100,100,100,100);
    lab1.setBounds(0,0,1500,700);
            welcome.add(lab1);
            welcome.add(b1);
            b1.setVisible(true);
    frame.setSize(500,500);
    frame.setVisible(true);
    frame.setTitle("I-Cloud");

}   
public static void main(String[] args) 
{

      try {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (Exception e) {

    }   
      ImageTest w = new ImageTest();
      w.createUI();   

     }
    }

EDIT:

 import javax.swing.ImageIcon;
 import javax.swing.JTabbedPane;
 import javax.swing.JTextField;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JButton;
 import javax.swing.JFrame;
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 import javax.swing.UnsupportedLookAndFeelException;
 import javax.swing.UIManager.LookAndFeelInfo;

 import java.awt.*;
 import java.awt.event.*;

 class ImageTest 
  {
 JTabbedPane tp;
 JLabel lab1;
 JPanel  welcome,w;
 JFrame frame;
 ImageIcon image2;
 JButton b1;

public void createUI()
{
    frame=new JFrame("JTabbedPane Example");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    b1=new JButton();
    welcome= new JPanel(new GridLayout(1,1,15,15));
    w=new JPanel (new GridLayout(1, 1, 15, 15));
    welcome.setPreferredSize(new Dimension(1366,786));

    ImageIcon icon = new ImageIcon(ImageTest.class.getResource("icloud.jpg"));

    tp=new JTabbedPane();
            Container pane = frame.getContentPane();
    pane.add(tp);


    lab1=new JLabel();
    lab1.setIcon(icon);
    w.setOpaque(false);
    w.add(b1);


    b1.setVisible(true);
            welcome.add(lab1);
            welcome.add(w);
            tp.addTab("Welcome", welcome);

    frame.setSize(500,500);
    frame.pack();
    frame.setVisible(true);
    frame.setTitle("I-Cloud");

}   
public static void main(String[] args) 
{
    try {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (Exception e) {

    }

        ImageTest w = new ImageTest();
        w.createUI();   

    }
  }

Thanks.

user3320152
  • 113
  • 2
  • 7
  • 2
    Please don't use `setBounds()` but a suitable [LayoutManager](http://docs.oracle.com/javase/tutorial/uiswing/layout/using.html) instead. This next comment is not personal at all so please don't get my wrong, but I think there is an academy or something where they teach people to use `setBounds()`, `setLocation()` and `setSize()` methods working with Swing which is plain wrong. There are at least 10 questions every day where developers use these methods. Please don't! – dic19 Feb 25 '14 at 14:54
  • 1
    See **[this answer](http://stackoverflow.com/questions/21970388/create-jcomponents-using-database)**. There are links in there to most frequent Q&A explaining why developers shouldn't use those methods. – dic19 Feb 25 '14 at 14:58
  • @dic19 It's perfectly legitimate to use `setBounds()` if there's no LayoutManager (even if it's a whole lot of extra work to do things well), and there are cases where using a LayoutManager is overkill (unnecessary processing). This is the 20% (or less) case, but it still exists. – Nick Rippe Feb 25 '14 at 15:12
  • 2
    @NickRippe do you think this is the case? In any case, Swing GUIs must be able to work with different L&F which implies for instance different font sizes which may cause issues as illustrated [here](http://stackoverflow.com/questions/12529200/non-resizable-window-border-and-positioning/12532237#12532237). So fixed locations/sizes through `setBounds()` is a way to shoot oneself in the foot. – dic19 Feb 25 '14 at 15:23
  • 1
    @dic19 - No, I don't think this is one of those special cases. But I also don't think it's right to say that there's never a place for those methods. How about "When you're learning, if you think you need to use them - you don't." – Nick Rippe Feb 25 '14 at 15:33
  • Oh, I'm sorry I didn't mean to be rude. I think my comment may have sounded a bit harsh in which case I apologize and don't have any problems on delete it. My point is every day we find too many questions involving this kind of issues generated by the incorrect use of methods I've pointed out. I was trying to emphasize (maybe too much:P) this is not the way to work with swing. @NickRippe – dic19 Feb 25 '14 at 15:49
  • 2
    @NickRippe: regardless, he shouldn't be putting his JLabel and JButton in a single container in the same location unless the container is a JLayeredPane, and he is careful with his z-order. I think that the original poster will have a much easier go of things if he learned about how to nest containers and use layout managers. I've no problem with occasional use of null layout in someone who is well versed in use of the layout managers and has a very good reason not to use them (such as for some animations), but not here. – Hovercraft Full Of Eels Feb 25 '14 at 17:22
  • @dic19- if setbounds() shouldn't be used then how do i set the location and size of a button? – user3320152 Feb 26 '14 at 06:54
  • 1
    @user3320152 is up to the Layout manager handle components positioning and sizing. Please see the answer I've linked above. There are some useful links in there, specially [Nested Layout Example](http://stackoverflow.com/questions/5621338/how-to-add-jtable-in-jpanel/5630271#5630271) which is a great example on how we should work with Swing. – dic19 Feb 26 '14 at 16:56

2 Answers2

4

Your use of Swing GUI is out of kilter by use of null layouts and then adding one component on top of another, essentially covering up one of the components (the JButton) with another (the JLabel with the image).

  • Don't use null layout like you're doing. While to a newbie using null layout and setBounds seems the best way to create complex GUI's, the more you deal with Swing GUI creation, the more you will find that doing this will put your GUI in a straight-jacket, painting it in a very tight corner and making it very hard to extend or enhance. Just don't do this.
  • Don't add one component on top of another in the same container.
  • Instead give your JLabel with the image a layout manager.
  • Then add the JButton to the JLabel.
  • Then add the JLabel to the JTabbedPane.

Edit
Your latest edit did not use the JLabel as the container as suggested above. So if you use a separate container, then the button and the label will be shown side by side. To solve this, you either need to give the JLabel a layout manager, and then add the button to it as suggested above, or draw directly in a JPanel's paintComponent(...) method, and add the button to the JPanel.

For an example of the latter:

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;

public class MyImageTest extends JPanel {
   // public static final String SPEC = "https://duke.kenai.com/SunRIP/.Midsize/SunRIP.jpg.png";
   public static final String SPEC = "http://upload.wikimedia.org/wikipedia/commons/3/37/"
         + "Mandel_zoom_14_satellite_julia_island.jpg";
   private static final int PREF_H = 786;
   private static final int GAP = 100;
   private BufferedImage img;

   public MyImageTest() {
      try {
         URL imgUrl = new URL(SPEC);
         img = ImageIO.read(imgUrl);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
      setLayout(new FlowLayout(FlowLayout.LEADING));
      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      JButton b = new JButton();
      b.setPreferredSize(new Dimension(GAP, GAP));
      add(b);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (img != null) {
         g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      if (img == null) {
         return super.getPreferredSize();
      } else {
         int width = (img.getWidth() * PREF_H) / img.getHeight();
         return new Dimension(width, PREF_H);
         // return new Dimension(img.getWidth(), img.getHeight());
      }
   }

   private static void createAndShowGui() {
      try {
         for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
               UIManager.setLookAndFeel(info.getClassName());
               break;
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
      MyImageTest mainPanel = new MyImageTest();

      JFrame frame = new JFrame("MyImageTest");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

enter image description here

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I added a line welcome= new JPanel(new GridLayout(2,2,5,10)); button is visible but it is not coming on the image. and the button size is not according to setbounds(). – user3320152 Feb 27 '14 at 04:17
  • @user3320152: please read all of my recommendations. Also, if you change your code, post your new code as an edit to your original question, but leave your old code in place. Let us be able to test your new code. – Hovercraft Full Of Eels Feb 27 '14 at 04:32
  • I have edited my code according to your procedure. But i can't set the location and size of the button. I want it exactly on the middle of the image. – user3320152 Feb 27 '14 at 09:54
  • Thanks a lot. But i tried setting the layout manager for JLabel as lab1=new JLabel(new GridLayout(1,1,15,15)); but it says this constructor is undefined. How do i do it for Jlabel? – user3320152 Feb 27 '14 at 13:46
  • @user3320152: you will want to make a habit out of using the Java API as it will tell you what constructors are available for use by all core Java classes. JLabel has no constructor like this (as you're finding out), but there is a method for it that JLabel shares with its parent class, JComponent. Please have a look in the Java API. – Hovercraft Full Of Eels Feb 27 '14 at 13:58
1

I think setting a background image in JLabel and then adding buttons even after adding containers is a very complex issue. Believe me tried it and it was a very complex task. you can do it by directly drawing as Hovercraft suggested, but remember you would get not so much good image quality with that method. :-|

sam
  • 83
  • 1
  • 7