1

Hi I am writing a simple program to display a frame. However the frame turns out real small when I type setLayout(null); But if i ignore this command, the button is always at the top center Can some one point out my error?

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

class theframe {

    private static void create() {
        JFrame frame = new JFrame("FrameDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Insets insets = frame.getInsets();
        frame.setSize(500 + insets.left + insets.right, 350 + insets.top + insets.bottom);
        add(frame.getContentPane()); //my function add
        frame.pack();
        frame.setVisible(true);
    }

    public static void add(Container pane) {
        pane.setLayout(null);
        Insets insets = pane.getInsets();

        JPanel p1 = new JPanel();
        p1.setPreferredSize(new Dimension(500, 350));

        JButton b1 = new JButton("one");
        Dimension size = b1.getPreferredSize();
        b1.setBounds(25 + insets.left, 5 + insets.top, size.width, size.height);

        pane.add(p1);
        p1.add(b1);
    }

    public static void main(String Args[]) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                create();
            }
        });
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Xperiaz X
  • 216
  • 1
  • 6
  • 16

4 Answers4

5

You're calling pack() method with absolute positioning (null layout), you should use LayoutManager instead of using setting the layout to null.

Just remove this line:

pane.setLayout(null);

NOTE: take my advice and learn yourself LayoutManagers, because if you refuse to learn, you'll probably go to null layout, yes,it is easier but highly recommended to not use it.

Some basic things you must know:

  1. The default layout of JFrame is BorderLayout, which there only five locations you can put your components in as shown in the link.
  2. FlowLayout is the default layout manager for every JPanel. It simply lays out components in a single row, starting a new row if its container is not sufficiently wide.

After all, read more about LayoutManagers before starting using swing, belive me it makes your work very easier, just try it, it's amazing.

Azad
  • 5,047
  • 20
  • 38
  • Yes but the button is always centered at the top and I cannot set its position on the panel – Xperiaz X Jul 25 '13 at 12:58
  • @Azdad using `pane.setPreferredSize(someDimension);` will solve the problem, you don't need to use a layout manager. It is better to use it when creating GUI applications, but the null layout is not the problem here. – BackSlash Jul 25 '13 at 13:00
  • 3
    *"I cannot set its position on the panel"* You **should not** be setting the position of components. – Andrew Thompson Jul 25 '13 at 13:00
  • @AndrewThompson Why not? Layout managers are a bit complex aren't they? – Xperiaz X Jul 25 '13 at 13:01
  • Yes, because by default the container of the frame adds the panel to the `CENTER`. – Azad Jul 25 '13 at 13:02
  • 2
    *"Why not?"* For the reasons I put in a comment 7 minutes ago. *"Layout managers are a bit complex aren't they?"* Less complex than figuring out positioning of components by yourself (for the **same** reasons). – Andrew Thompson Jul 25 '13 at 13:06
  • @BackSlash: it's not about his problem, it's about changing him to not use `null` layout, and about `pane.setPreferredSize` method, dont do anything until specifying the location and the size of the panel using `setBounds(x,y,width,height)`. – Azad Jul 25 '13 at 13:06
5

If you see the pack() function it is not in JFrame.java but Window.java

public void pack() {
    Container parent = this.parent;
    if (parent != null && parent.getPeer() == null) {
        parent.addNotify();
    }
    if (peer == null) {
        addNotify();
    }
    Dimension newSize = getPreferredSize();
    if (peer != null) {
        setClientSize(newSize.width, newSize.height);
    }

    if(beforeFirstShow) {
        isPacked = true;
    }

    validateUnconditionally();
}

now if you see getPreferredSize() function in Container.java

@Deprecated
public Dimension preferredSize() {
    /* Avoid grabbing the lock if a reasonable cached size value
     * is available.
     */
    Dimension dim = prefSize;
    if (dim == null || !(isPreferredSizeSet() || isValid())) {
        synchronized (getTreeLock()) {
            prefSize = (layoutMgr != null) ?
                layoutMgr.preferredLayoutSize(this) :
                super.preferredSize();
            dim = prefSize;
        }
    }
    if (dim != null){
        return new Dimension(dim);
    }
    else{
        return dim;
    }
}

Everything boils down to layoutMgr.preferredLayoutSize(this); Since you are not setting the layout(or null) you are getting that issue. Either remove that statement or use some layout.

Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
2

Java GUIs might have to work on a number of platforms, on different screen resolutions & using different PLAFs. As such they are not conducive to exact placement of components.

To organize the components for a robust GUI, instead use layout managers, or combinations of them, along with layout padding & borders for white space.

See this answer for tips on how to:

  1. Combine layouts.
  2. Provide white space using layout constructor arguments & borders.

Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
1

I had the same issue luckly, I solved with one line code. May this will also help you try to follow these steps:

1- Goto in your file code

2- In start of code find this line:

            initComponents();

3- Just add this new code after this line:

this.setMinimumSize(new Dimension(300, 300));

The keyword "this" here representing your current top-level component, so new dimensions as (300, 300) is applied here. You may change this 300 values according to your required frame / component size.

A.Aleem11
  • 1,844
  • 17
  • 12