3

So I have a class called CalendarPanel that extends JPanel. It uses a null layout. How would I use CalendarPanel as a regular component? When I put it in another JPanel and then add it to a window, it disappears. It is only visible when I add it directly to a window.

EDIT: And yes, I realize using a JPanel with a null layout is bad practice. CalendarPanel is actually someone else's code, and I'm trying to use it for my purposes without having to refactor it.

Joel Christophel
  • 2,604
  • 4
  • 30
  • 49
  • 10
    *"Using a JPanel with a null layout"* ***Doooooooooooon't!*** – Andrew Thompson Feb 20 '13 at 14:56
  • *"..CalendarPanel that extends JPanel"* Why? Or rather, why not simply use an instance of a panel? – Andrew Thompson Feb 20 '13 at 14:58
  • Please show your code. – slawter Feb 20 '13 at 15:12
  • 1
    @Andrew Thompson, Why not make a class that extends JPanel? I'm making a rather large application, so I'm creating different classes for the various GUI components so as to stay somewhat organized. – Joel Christophel Feb 21 '13 at 04:10
  • *"stay somewhat organized"* I don't see the connection. I could create a class for a `CalendarComponent` that does not explicitly extend anything, with a `getGui()` method that creates and returns a `JComponent` (that might be a `JPanel` or other things). In general, see [inheritance vs composition](http://en.wikipedia.org/wiki/Composition_over_inheritance). – Andrew Thompson Feb 21 '13 at 04:16
  • 1
    Now I understand what you were saying. As mentioned in my edit above, it's not my code. – Joel Christophel Feb 21 '13 at 04:34

2 Answers2

9

It is only visible when I add it directly to a window.

That is because a window uses a BorderLayout by default and will automatically resize the panel to fit in the window.

When I put it in another JPanel and then add it to a window, it disappears.

The is because a JPanel uses a FlowLayout by default and a flow layout respects the preferred size of the components added to it. Since you are using a null layout your panel doesn't have a preferred size so nothing gets painted.

That is why you should NOT use null layout. Instead use layout managers because they do all this extra work for you.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • So is there any workaround to get it to appear in another JPanel? – Joel Christophel Feb 21 '13 at 04:05
  • Use layout managers since they will determine the preferred size for you. If you don't use a layout manager then you are responsible for overriding the getPreferredSize() method to return the size of your panel. – camickr Feb 21 '13 at 04:22
  • That doesn't sound too awful. – Joel Christophel Feb 21 '13 at 04:35
  • Have you read all the comments??? Everybody recommends using a layout manager because calculating the preferred size of a panel is not easy which is why everybody else lets the layout manager do its job. Sure you can pick random numbers like (200, 200), but that doesn't mean anything and you will get an ugly GUI that is not easy to change. – camickr Feb 21 '13 at 05:03
6

NOTE: it is a very bad idea in general to use a null layout. Use a LayoutManager instead.

If you insist on using a null layout, you're going to have to position the JPanel manually as mentioned in the documentation. Here's an example.

enter image description here

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Test extends JFrame {
   static int defaultX = 10;
   static int defaultY = 10;
   static int defaultW = 150;
   static int defaultH = 50;

   public Test() {
      super("Test");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      // here is the outer JPanel
      final JPanel outer = new JPanel(new BorderLayout());
      JPanel inner = new JPanel(new BorderLayout());
      // here is the main component we want to see
      // when the outer panel is added to the null layout
      JButton mainComponent = new JButton("Test");
      inner.add("Center", mainComponent);
      outer.add("Center", inner);

      JPanel c = (JPanel)getContentPane();

      // This panel has a null layout!
      final JPanel nullLayoutPanel = new JPanel();
      nullLayoutPanel.setLayout(null);
      c.add("Center", nullLayoutPanel);

      // set the bounds of the outer panel manually
      // when using the null layout!
      nullLayoutPanel.add(outer);
      outer.setBounds(defaultX, defaultY, defaultW, defaultH);

      JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
      final JTextField x = new JTextField(""+defaultX, 3);
      final JTextField y = new JTextField(""+defaultY, 3);
      final JTextField w = new JTextField(""+defaultW, 3);
      final JTextField h = new JTextField(""+defaultH, 3);
      JButton b = new JButton("Resize");
      b.addActionListener(
         new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               try {
                  outer.setBounds(
                        Integer.parseInt(x.getText()),
                        Integer.parseInt(y.getText()),
                        Integer.parseInt(w.getText()),
                        Integer.parseInt(h.getText())
                  );
                  outer.revalidate();
               } catch(Exception ex) {}
            }
         }
      );
      controlPanel.add(x);
      controlPanel.add(y);
      controlPanel.add(w);
      controlPanel.add(h);
      controlPanel.add(b);
      c.add("South", controlPanel);
   }

    public static void main(String[] argv) {
       SwingUtilities.invokeLater(new Runnable() {
          public void run() {
             Test p = new Test();
             p.setSize(300, 200);
             p.setVisible(true);
          }
      });
    }
}
808sound
  • 7,866
  • 1
  • 15
  • 13
  • Why? Using a null layout may not be best practice, but it certainly is an option. Did you read my link to the official Java documentation regarding this? – 808sound Feb 20 '13 at 17:23
  • 1
    it's an option only for developers with a extreme masochistic stroke ;-) Not everything that's doable should be done, especially not if there's not the very rare odd corner case requiring extreme measures. This context is not. – kleopatra Feb 20 '13 at 17:29
  • 6
    Yes, but why does this answer merit a -1? What is technically wrong with it, aside from the fact that most developer's don't like null layout? – 808sound Feb 20 '13 at 17:30
  • 1
    it's technically wrong to advice using a null layout if it's not required – kleopatra Feb 20 '13 at 17:31
  • 6
    I didn't advise it, I straightforwardly answered the OP's question. Would it help if I add a disclaimer that this is a bad idea in general? – 808sound Feb 20 '13 at 17:32
  • 1
    yeah, it certainly would help to add a **strong** disclaimer :-) – kleopatra Feb 20 '13 at 17:33