0

I can not seem to figure this out for the life of me. Excuse me if there is redundant code but I kept trying and trying and couldn't figure it out. The JFrame shows up but the button and label are not appearing.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class ex03 {

     int w = 20;
     int h = 20;

     public ex03() {
         JFrame fra = new JFrame("");
         fra.setBounds(10, 10, 200, 200);
         fra.setLayout(null);
         fra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         fra.setVisible(true);

         JPanel pan = new JPanel();
         pan.setLayout(null);
         pan.setVisible(true);
         fra.getContentPane().add(pan);

         JLabel lab = new JLabel();
         lab.setBounds(10, 10, w, h);
         lab.setOpaque(true);
         lab.setBackground(Color.blue);
         lab.setVisible(true);

         JButton but = new JButton("Play");
         but.setBounds(10, 10, 100, 35);
         but.addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent e) {
                 w++;
                 h++;
             }
         });
         but.setVisible(true);

         pan.add(lab);
         pan.add(but);
     }

     public static void main (String[] args) {
         new ex03();
     }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Pseudonym
  • 1
  • 3
  • 2
    `fra.setLayout(null)` is the start of your problems. Avoid using `null` layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify – MadProgrammer Nov 08 '14 at 22:17
  • 2
    See [Why is it frowned upon to use a null layout in SWING?](http://stackoverflow.com/questions/6592468/why-is-it-frowned-upon-to-use-a-null-layout-in-swing) for more details – MadProgrammer Nov 08 '14 at 22:18

3 Answers3

3

You need a call to fra.setVisible(true); after you add the visible elements to the content pane.

ncmathsadist
  • 4,684
  • 3
  • 29
  • 45
3

The problem is you add both the button and label after the top-level container (window) is made visible. Thus the components hierarchy must be revalidated in order to make the components visible as well:

pan.add(lab);
pan.add(but);
pan.revalidate();
pan.repaint();

As per Container#add(Component comp) documentation:

This method changes layout-related information, and therefore, invalidates the component hierarchy. If the container has already been displayed, the hierarchy must be validated thereafter in order to display the added component.

On the other hand a better practice is pack and make the window visible after adding all the components, so the components hierarchy is validated only once.

pan.add(lab);
pan.add(but);
...
frame.add(pan);
frame.pack();
frame.setVisible(true);

Other comments

Please note that Swing is designed to work with Layout Managers and thus methods such as setBounds(...), setLocation(...) and setXxxSize(...) are discouraged. Components position and size is a layout manager's responsibility not developer's, unless you have a very good reason to do it. From the very Doing Without a Layout Manager (Absolute Positioning) section:

Although it is possible to do without a layout manager, you should use a layout manager if at all possible. A layout manager makes it easier to adjust to look-and-feel-dependent component appearances, to different font sizes, to a container's changing size, and to different locales. Layout managers also can be reused easily by other containers, as well as other programs.

dic19
  • 17,821
  • 6
  • 40
  • 69
  • 1
    nb: `invalidate`, `revalidate`, `validate` all deal within the layout manager API, so unless they take your, excellent, second advice, it is pointless calling them... ;) – MadProgrammer Nov 08 '14 at 22:18
  • Update: funny thing, it is stated in [the docs](https://docs.oracle.com/javase/8/docs/api/java/awt/Container.html#validate--) and always overlooked the layout manager inference. @MadProgrammer – dic19 Nov 08 '14 at 22:34
0

A combination of making parent frame visible and updating the child component graphics will work:

fra.setVisible(true);
progressLabel.update(progressLabel.getGraphics());
Renjith Thomas
  • 147
  • 1
  • 4