0

I wrote the following code which is a simple window with a JLabel header at the top. The code is as follows:

import java.awt.Color;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public class Main extends JFrame {

private static final long serialVersionUID = 1L;

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

public Main() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    int WIDTH = 500;
    int HEIGHT = 500;
    setBackground(Color.LIGHT_GRAY);
    setSize(WIDTH, HEIGHT);
    setTitle("New Window");
    setLocationRelativeTo(null);

    JPanel pane = new JPanel();
    pane.setOpaque(false);
    setContentPane(pane);
    pane.setLayout(null);

    JLabel title = new JLabel("New Window", SwingConstants.CENTER);
    title.setFont(new Font("Neuropol", Font.PLAIN, 22));
    title.setSize(WIDTH, 20);
    title.setBorder(BorderFactory.createLineBorder(Color.black));
    pane.add(title);
}

static void init() {
    Main frame = new Main();
    frame.setVisible(true);
}

}

I'm having a weird issue with it though. As you can see I set the width of the JLabel to the same width as the JFrame (and therefore the same width as the JPanel), but for some reason, the label goes past the right edge of the Frame. The width of the frame is 500, but I have to set the JLabel to a width of 483 in order for the border to be within the JFrame. I've been over and over this, but can't see anything wrong. Does anybody see my mistake here?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user3226170
  • 175
  • 1
  • 1
  • 14
  • 5
    This is your main problem here: `pane.setLayout(null);`. Simply don't do this. If you need the JLabel to be the same size as its container, then have the container use a decent layout manager that will size the components appropriately. – Hovercraft Full Of Eels Mar 17 '16 at 01:45

1 Answers1

3

I set the width of the JLabel to the same width as the JFrame

But the JFrame width includes the "decorations" of the frame, like the Border.

I have to set the JLabel to a width of 483 in order for the border to be within the JFrame.

No, 483 will make the label too big for the frame. The Borders of the frame are not 17 pixels. I think the Borders are 4 or 5 pixels each depending on the LAF.

So this is another reason why you should NOT be using a null layout as hardcoding a value for one LAF may not work on another LAF.

Also, what happens if the user resizes the frame wider? Now the label will not go to the end. Use a Layout Manager do design dynamic GUI's that adapt to changes as the user resizes the frame.

The easiest solution is to just use the default BorderLayout of content pane of the frame. Then you add your label to the PAGE_START.

add(title, BorderLayout.PAGE_START);

There is also no reason to create a content pane. The frame already has a JPanel which uses a BorderLayout.

Read the Swing tutorial on Layout Managers for more information and working examples. Download the demos code and use them as a starting point for your code. The demo code will show you how to better structure your code to follow Swing conventions.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • I dug through the Java Tutorials page on layouts before making this post, but wasn't able to find a layout that matched what I wanted to do. For the Border Layout, I was limited to 5 components, which won't really work. I want to have a JLabel header (as above), then 3 to 5 buttons down the left hand side, with a box about 200x200 to the right of the buttons. Any suggestions as to a layout manager that would suit that? – user3226170 Mar 17 '16 at 02:57
  • So you can add a panel with as many components as you want to each of the 5 areas. Each panel can use a different layout manger. So the idea is the you nest panels with different layout managers to get the desired layout. – camickr Mar 17 '16 at 03:59
  • *"wasn't able to find a layout that matched what I wanted to do"* Layouts can be [combined](http://stackoverflow.com/a/5630271/418556).. Provide ASCII art or a simple drawing of the *intended* layout of the GUI at minimum size, and if resizable, with more width and height. – Andrew Thompson Mar 17 '16 at 04:01
  • Using Border Layout, I ran into 2 initial issues, Although the header worked fine, when I went to add a second JLabel to `LINE_START` the label took the entire size of the layout region. I tried resizing it using `label.setPreferredSize(new Dimension(200, 100));` and it set the x dimension, but did not affect the y (It just took up the entire hight of the frame less the header region). The second issue was that in adding a third label (also to `LINE_START`), it simply covered up the other label in `LINE_START`. – user3226170 Mar 17 '16 at 23:47
  • The requirement of this question what to have the label span the width of the frame which is exactly what the Borderlayout.PAGE_START is for. Yes, only a single component can be added to each area of the BorderLayout. If you want multiple components, then you add the multiple components to a JPanel and then add the panel to the PAGE_START. The panel should use an appropriate layout manager. You should never play with the setPreferredSize() method. The component know better that you what the size should be. Some layout managers, like the BorderLayout will ignore the preferred size suggestion. – camickr Mar 18 '16 at 01:30
  • Ah ok, that makes sense. I'll try that out. Thanks! – user3226170 Mar 18 '16 at 01:59