0

Hello i am developing a custom clock application.

My GUI works find my functionality is fine however i have one problem for 3 days now. I can't get my GUI to display an image in the background without hiding my components.

here is my code of the GUI class

public void makeFrame()  {
    contentPane.setLayout(new BorderLayout());
    contentPane.add(panel1, BorderLayout.NORTH);
    contentPane.add(panel2, BorderLayout.CENTER);
    contentPane.add(panel3, BorderLayout.SOUTH);
    contentPane.add(panel4, BorderLayout.WEST);
    contentPane.add(panel5, BorderLayout.EAST);
    panel1.add(label1);
    panel2.setLayout(new GridLayout(3,4));
    panel2.add(time);
    panel2.add(label2);
    panel2.add(stopwatch);
    panel3.setLayout(new FlowLayout());
    panel4.setLayout(new FlowLayout());
    panel5.add(alarm);
    panel5.add(change);
    panel5.setLayout(new FlowLayout());
    label1.setFont(new Font("Arial", Font.PLAIN, 90));
    label1.setForeground(Color.BLUE);
    label2.setFont(new Font("Arial", Font.PLAIN, 70));
    label2.setForeground(Color.RED);
    time.setEditable(true);
    time.setText("Sample Time: n/ 13:45:23 ");
    time.setFont(new Font("Arial", Font.PLAIN, 60));
    stopwatch.setFont(new Font("Arial", Font.PLAIN, 45));
    stopwatch.setSize(20,20);
    stopwatch.setText("00 : 00 : 00");
    stopwatch.setEditable(false);
    stopwatch.add(rounds);

    frame = new JFrame("Clock");
    frame.setLayout(null);
    frame.setSize(600,900);
    paint();
    frame.setContentPane(contentPane);
    makeMenu();
    comboBox();
    stopWatch();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.validate();
    frame.pack();
    frame.setVisible(true);
    frame.setLocationRelativeTo(null);


}

and the paint() method

 public void paint() {
     BufferedImage img = null;
        try {
            //load the image
            img = ImageIO.read(new File("C:/Users/User/workspace/Alarm Clock/src/Clock/clock.jpg"));

            ImageIcon image = new ImageIcon(img);
            JLabel label = new JLabel(image);
            frame.setContentPane(label);

        } catch (IOException e) {

        }
 }
Eilleen
  • 357
  • 1
  • 16
  • 1
    You're replacing the content pane which contains the other components with that label. Try using a card layout for the content pane and set the label at the lowest level or override the frame's paint() method and add the image there: http://stackoverflow.com/questions/1466240/how-to-set-an-image-as-a-background-for-frame-in-swing-gui-of-java – Thomas Jul 10 '15 at 15:33
  • 1
    Never leave an exception block empty. (This has nothing to do with your problem but could be related to a future problem.) – Risadinha Jul 10 '15 at 16:12
  • @Thomas, `Try using a card layout` - a CardLayout only ever displays one component at a time, this will not work. Also, the "accepted" answer in the link you provided is incomplete because nowhere does it mention you need to use `setOaque(false)` on the panels you add to the content pane so the background image can be seen. – camickr Jul 10 '15 at 16:44

3 Answers3

2
contentPane.add(panel1, BorderLayout.NORTH);
contentPane.add(panel2, BorderLayout.CENTER);

Your code is adding panels to the content pane, which is fine.

frame.setContentPane(label);

But then in the paint() method you replace the content pane with the label, so you lose all the original panels.

First of all, you should NOT override paint() on a JFrame. If you ever do custom painting you should override the paintComponent() method of a JPanel and add the panel to the frame. Also, a painting method is for painting only, you should NVEVER create and add a component to the GUI in a painting method. YOu should also NOT read an image in a painting method. Painting should be very efficient.

So to solve your problem I suggest you can use the BackgroundPanel. This is a custom panel that supports painting of images and it will make any component you add to it non-opaque. You can paint the background image 1) at its original size, 2) scaled to fill the panel, 3) tiled.

The basic code would be:

//contentPane.setLayout(new BorderLayout());
BackgroundPanel contentPane = new BackgroundPanel(...); // choose your constructor
frame.setContentPane( contentPane );
contentPane.add(panel1, BorderLayout.NORTH);
...
camickr
  • 321,443
  • 19
  • 166
  • 288
0

I think what you are looking for is setOpaque

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
  • Hmm, I don't think that would help since the OP is replacing the content pane and thus detaches the components from the frame. I might be mistaken here (didn't do Swing in years) and if so please explain why and how `setOpaque()` would help the OP. – Thomas Jul 10 '15 at 16:17
0

You can try this

setContentPane(new javax.swing.JLabel(new javax.swing.ImageIcon(getClass().getResource("background_image.jpg"))));

or you can draw on your JFrame and add a JPanel on it. Now add your components on your JPanel. Make sure you make the JPanel not opaque .This always comes easy setting background images.

Rahul
  • 289
  • 2
  • 7
  • I'm not sure how your first suggestion is much different from what the OP already tried (besides it being all in one line). – Thomas Jul 10 '15 at 16:14
  • Putting a JLabel on the the contentPane and setting whatever background we set does not effect the components on the JFrame. The only draw back is the whole JFrame will take the size of the background image provided. For this reason it creates problem if background image is changed – Rahul Jul 11 '15 at 03:57
  • The one liner is the quick solution , but my second suggestion makes more sense. – Rahul Jul 11 '15 at 03:58