1

I am creating a GUI with a graphics panel, a command panel and a Command List panel. I've got the command panel where I want it at the bottom of the frame using BorderLayout South but my side panel is just tiny and unreadable.

Ill provide a picture of what I want my frame to look like at the end:

enter image description here

What I currently have:

enter image description here

Could anyone explain why the TitledBorder panel is so small?

My code is below:

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class PenDriver {

public static void main(String[] args) {

    JFrame frame = new JFrame("Pen Simulator");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 400);

    penPanel panel = new penPanel();

    frame.add(panel);

    frame.setVisible(true);

}

}

AND

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;

public class penPanel extends JPanel {

private JTextField userCommand;
private JLabel instruction1;
private JButton instruct, clear;
private JLabel cmd1;

public penPanel() {

    setLayout(new BorderLayout());

    // CREATE THE COMMAND PANEL///////

    // Set Layout
    JPanel command = new JPanel();
    command.setLayout(new BoxLayout(command, BoxLayout.LINE_AXIS));
    // Create Label and add to panel
    instruction1 = new JLabel("Enter Command:");
    // Create Buttons
    instruct = new JButton("Execute");
    clear = new JButton("Clear Graphics");

    // Create Text Field to panel
    userCommand = new JTextField(10);

    command.add(instruction1);
    command.add(Box.createRigidArea(new Dimension(4, 0)));
    command.add(userCommand);
    command.add(Box.createRigidArea(new Dimension(2, 0)));
    command.add(instruct);
    command.add(Box.createRigidArea(new Dimension(2, 0)));
    command.add(clear);

    // COMMAND PANEL FINISHED////////

    // CREATE THE COMMAND LIST PANEL//////////
    JPanel cmdList = new JPanel();
    cmdList.setBorder(BorderFactory.createTitledBorder("Command List:"));
    cmdList.setLayout(new BoxLayout(cmdList, BoxLayout.PAGE_AXIS));
    cmd1 = new JLabel("UP = up");
    cmdList.setSize(new Dimension(50, 400));
    cmdList.add(cmd1);

    add(command, BorderLayout.SOUTH);
    add(cmdList, BorderLayout.EAST);

}

}

Thank you!

EDIT: After some tinkering to this code:

    cmdList.setPreferredSize(new Dimension(120, 800));
    cmdList.add(cmd1);

    add(command, BorderLayout.SOUTH);
    command.add(Box.createRigidArea(new Dimension(120, 0)));
    add(cmdList, BorderLayout.EAST);

enter image description here

Still not quite what im going for and not sure if it's what I am supposed to do. Should I be altering the driver file rather than the JPanels directly?

Notice how there is still a gap to the right of the "Clear Graphics" Button. Any way to get rid of that?

SkyPlus
  • 105
  • 1
  • 9
  • Try to use `setPreferredSize` instead of `setSize` for the right panel. – Arnaud Apr 04 '16 at 14:28
  • [Don't use `setPreferredSize()` when you really mean to override `getPreferredSize()`](http://stackoverflow.com/q/7229226/230513). – trashgod Apr 04 '16 at 14:31
  • @trashgod : thanks for the link, this is interesting. – Arnaud Apr 04 '16 at 14:35
  • You shouldn't have to even call setPreferredSize(). BorderLayout will call cmdList. getPreferredSize(), letting it determine the size it needs to be based on its contents, and then make the EAST panel just large enough to fit. Setting a particular size is almost always wrong, since you will have change that size if you modify the content of that panel, or change the font for anything in that panel. (However, if your component is inside a JScrollPane, then you can set the preferred size of the ScrollPane, letting it add scroll bars if the content is larger than your specified size) – FredK Apr 04 '16 at 14:42
  • @fred, That is why the link was given to say you should override the `getPreferredSize()` method, which can be a valid solution. The problem is that the text in the border is NOT used in the preferred size calculation of the panel. So one solution could be override the getPreferredSize() method of the panel to return the maximum of the default preferred width of the width of the text in the titled Border. So overriding the preferred size can be a valid solution in this case. – camickr Apr 04 '16 at 14:47

1 Answers1

1

Could anyone explain why the TitledBorder panel is so small?

The size of the text in the border is not used to determine the size of the component. So the width is determined by the preferred size of the component you add to the panel.

So you need to override the getPreferredSize() method of the panel to return the maximum of the default preferred size calculation or the size of the titled border:

JPanel cmdList = new JPanel()
{
    @Override
    public Dimension getPreferredSize()
    {
        Dimension preferredSize = super.getPreferredSize();

        Border border =    getBorder();
        int borderWidth = 0;

     if (border instanceof TitledBorder)
     {
         Insets insets = getInsets();
         TitledBorder titledBorder = (TitledBorder)border;
         borderWidth = titledBorder.getMinimumSize(this).width + insets.left + insets.right;
     }

     int preferredWidth = Math.max(preferredSize.width, borderWidth);

     return new Dimension(preferredWidth, preferredSize.height);
    }
};

Notice how there is still a gap to the right of the "Clear Graphics" Button. Any way to get rid of that?

command.add(Box.createRigidArea(new Dimension(120, 0)));

You just added the rigid area to the command panel so you asked to have the extra 120 pixels at the end.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Okay I have done that and posted the results above. I didn't do it with panel.add though I did it by altering these lines: cmdList.setPreferredSize(new Dimension(120, 800)); cmdList.add(cmd1); add(command, BorderLayout.SOUTH); command.add(Box.createRigidArea(new Dimension(120, 0))); add(cmdList, BorderLayout.EAST); – SkyPlus Apr 04 '16 at 14:46
  • Will post it in an edit above as doesnt post well here. – SkyPlus Apr 04 '16 at 14:47
  • @SkyPlusk, NO, never use setPreferredSize()!!! You are just making a random guess at the size of the titled border. It is the job of the layout manager to determine the preferred size. See my updated answer for the proper way to solve this problem. – camickr Apr 04 '16 at 15:46
  • What is the if statement stating? I understand the top part of the code in that youre overriding a method with your own parameters but mind explaining the insets part etc. Thanks – SkyPlus Apr 04 '16 at 16:32
  • @SkyPlus, The Insets provide the space reserved for the Border on the top/left/bottom/right. That is the space required to paint the line around the component. The other method gets the length of the text of the Border. – camickr Apr 04 '16 at 16:44
  • Ah thank you, I understand the code now. I am however getting several syntax errors when I add this in. – SkyPlus Apr 04 '16 at 16:48
  • @SkyPlus, `I am however getting several syntax errors` - all you need to do is replace the statement where you create your panel with the code presented here. – camickr Apr 04 '16 at 17:00
  • Ah okay thank you, realise where my error was. It functions now however I was wondering if you look at my above draft image where the Command list is youll notice that it is to the right of the command panel however mine currently sits on top. Any way to change this? – SkyPlus Apr 04 '16 at 17:07
  • @SkyPlus, `if you look at my above draft image` - you need to nest panels. The frame will still use a BorderLayout. Then you create a second panel that uses a BorderLayout. You add your command panel to the SOUTH and then add this second panel to the CENTER of the frame. The command list panel still is added to the EAST of the frame. – camickr Apr 04 '16 at 17:34
  • Yes it does function, have accepted the answer. Just would really appreciate it if you could help me on the getting the command help panel to the left of the command panel as some of the commands and their descriptions are very long meaning it takes up a sizeable chunk of the screen – SkyPlus Apr 04 '16 at 17:35
  • @SkyPlus, I already answer that. The solution is to nest panels. – camickr Apr 04 '16 at 17:49
  • Apologies, my comment came before I had seen that. Struggling to understand what you mean though. The way im seeing it is that I have created two JPanels, the command panel with the two buttons and the Command help panel which is filled with lots of lables (still not sure this is the best way to go about it). and I have assigned that to be on the east which means that surely it shouldnt be sitting on top of the south panel. Really struggling to get this – SkyPlus Apr 04 '16 at 18:10
  • @SkyPlus `surely it shouldnt be sitting on top of the south panel.` - yes it should because the BorderLayout has the NORTH and SOUTH panels fill the entire width of the frame. See the section from the Swing tutorial on [How to Use BorderLayout](http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html) for more information. That is why you need to add a CENTER and EAST panel to the frame. Then you need to divide the CENTER panel to contain your GraphicsPanel and CommandPanel. – camickr Apr 04 '16 at 19:20