How to surround Java Swing components with border?

45,462

Solution 1

When using Absolute Positioning, you have to provide Location for each and every component, that will become a part of the view. Hence without looking at exactly what you doing it's hard to predict where exactly the things are going wrong. Though using Layout Managers, will remove this big burden off your shoulders regarding placement of different components on the view.

Moreover, you have to set the border for the respective component. So in no way I can assume that you added one component and it appeared between two borders (though considering the fact that you using Absolute Positioning, you might have given the wrong Co-ordinates for the said component on the view). Please have a look at this example code, that might can help you a bit in this direction :

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

public class BorderExample
{
    private JPanel topPanel;
    private JPanel centerPanel;
    private JPanel bottomPanel;
    private int hgap;
    private int vgap;
    private JTextField tfield1, tfield2;
    private JComboBox cbox1, cbox2;
    private String[] data = {"One", "Two"};

    public BorderExample()
    {
        hgap = 5;
        vgap = 5;
    }

    private void displayGUI()
    {
        JFrame frame = new JFrame("Border Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setOpaque(true);
        contentPane.setBackground(Color.WHITE);
        contentPane.setBorder(
            BorderFactory.createEmptyBorder(hgap, hgap, hgap, hgap));
        contentPane.setLayout(new BorderLayout(hgap, vgap));

        topPanel = new JPanel();
        topPanel.setOpaque(true);
        topPanel.setBackground(Color.WHITE);
        topPanel.setBorder(
            BorderFactory.createTitledBorder("Top Panel"));
        tfield1 = new JTextField(10);   
        tfield1.setBorder(
            BorderFactory.createTitledBorder(
            BorderFactory.createEtchedBorder(
                    EtchedBorder.RAISED, Color.GRAY
                    , Color.DARK_GRAY), "JTextField"));
        JPanel comboPanel = new JPanel();           
        cbox1 = new JComboBox(data);
        cbox1.setBorder(
            BorderFactory.createTitledBorder("JComboBox")); 
        topPanel.add(tfield1);  
        topPanel.add(cbox1);

        centerPanel = new JPanel(); 
        centerPanel.setOpaque(true);
        centerPanel.setBackground(Color.WHITE);
        centerPanel.setBorder(
            BorderFactory.createTitledBorder("Center Panel"));
        tfield2 = new JTextField(10);   
        tfield2.setBorder(
            BorderFactory.createLoweredBevelBorder());
        cbox2 = new JComboBox(data);
        cbox2.setBorder(
            BorderFactory.createRaisedBevelBorder());   
        centerPanel.add(tfield2);   
        centerPanel.add(cbox2);

        bottomPanel = new JPanel(); 
        bottomPanel.setOpaque(true);
        bottomPanel.setBackground(Color.WHITE);
        bottomPanel.setBorder(
            BorderFactory.createTitledBorder("Center Panel"));

        contentPane.add(topPanel, BorderLayout.PAGE_START);
        contentPane.add(centerPanel, BorderLayout.CENTER);
        contentPane.add(bottomPanel, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new BorderExample().displayGUI();
            }
        });
    }
}

Here is the output of the same :

BORDER_EXAMPLE

Solution 2

OK, so this solves a big part of my concerns regarding usage of Layout Manager and adding borders to groups of components:

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.*;

public class TestingGround extends JFrame {

private JTextField tLenUnit, tLenResult, tAreUnit, tAreResult;
private JComboBox<String> cLenInUnit, cLenOutUnit, cAreInUnit, cAreOutUnit;
private JPanel lenMicro, lenMicro1, lenMicro2, lenNormal, lenMacro, area, volume;
private Border bGreyLine, bTitled1, bTitled2;

private TestingGround() {

    setTitle("Testing Ground for an Application");
    setVisible(true);
    setResizable(true);
    setLocationRelativeTo(null);

    try {
        UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }

    lenMicro = new JPanel();
    lenMicro.setLayout(new GridBagLayout());

    lenMicro1 = new JPanel();
    lenMicro1.setLayout(new GridBagLayout());

    bGreyLine = BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true);
    bTitled1 = BorderFactory.createTitledBorder(bGreyLine, "Length", TitledBorder.LEFT, TitledBorder.TOP);
    lenMicro1.setBorder(bTitled1);

    tLenUnit = new JTextField("0.0");
    tLenUnit.setColumns(10);
    lenMicro1.add(tLenUnit, new GBC(0, 0, 2, 1).setAnchor(GBC.WEST).setInsets(5, 5, 5, 5));

    cLenInUnit = new JComboBox<String>();
    cLenInUnit.addItem("");
    cLenInUnit.addItem("First");
    cLenInUnit.addItem("Second");
    cLenInUnit.setSelectedIndex(0);
    cLenInUnit.setPreferredSize(new Dimension(120, 25));
    lenMicro1.add(cLenInUnit, new GBC(2, 0, 3, 1));

    tLenResult = new JTextField("");
    tLenResult.setColumns(10);
    lenMicro1.add(tLenResult, new GBC(5, 0, 2, 1).setInsets(5, 5, 5, 5));

    cLenOutUnit = new JComboBox<String>();
    cLenOutUnit.addItem("First");
    cLenOutUnit.addItem("Second");
    cLenOutUnit.setSelectedIndex(1);
    cLenOutUnit.setPreferredSize(new Dimension(120, 25));
    lenMicro1.add(cLenOutUnit, new GBC(7, 0, 1, 1));

    // Area part:

    lenMicro2 = new JPanel();
    lenMicro2.setLayout(new GridBagLayout());

    bTitled2 = BorderFactory.createTitledBorder(bGreyLine, "Area", TitledBorder.LEFT, TitledBorder.TOP);
    lenMicro2.setBorder(bTitled2);

    tAreUnit = new JTextField("0.0");
    tAreUnit.setColumns(10);
    lenMicro2.add(tAreUnit, new GBC(0, 1, 2, 1).setAnchor(GBC.WEST).setInsets(5, 5, 5, 5));

    cAreInUnit = new JComboBox<String>();
    cAreInUnit.addItem("");
    cAreInUnit.addItem("One sqm");
    cAreInUnit.addItem("Two sqm");
    cAreInUnit.setSelectedIndex(0);
    cAreInUnit.setPreferredSize(new Dimension(120, 25));
    lenMicro2.add(cAreInUnit, new GBC(2, 1, 3, 1));

    tAreResult = new JTextField("");
    tAreResult.setColumns(10);
    lenMicro2.add(tAreResult, new GBC(5, 1, 2, 1).setInsets(5, 5, 5, 5));

    cAreOutUnit = new JComboBox<String>();
    cAreOutUnit.addItem("One sqm");
    cAreOutUnit.addItem("Two sqm");
    cAreOutUnit.setSelectedIndex(1);
    cAreOutUnit.setPreferredSize(new Dimension(120, 25));
    lenMicro2.add(cAreOutUnit, new GBC(7, 1, 1, 1));

    // Joining all lenMicroX panels into one:

    lenMicro.add(lenMicro1, new GBC(0, 0, 8, 1).setAnchor(GBC.FIRST_LINE_START).setInsets(5, 5, 5, 5).setIpad(10, 10));
    lenMicro.add(lenMicro2, new GBC(0, 1, 8, 1).setAnchor(GBC.LINE_START).setInsets(5, 5, 5, 5).setIpad(10, 10));

    volume = new JPanel();
    volume.setLayout(null);

    // Panel definition --begin:

    JTabbedPane tPane = new JTabbedPane();

    tPane.addTab("Length & Area", null, lenMicro, "Length & Area units");
    tPane.addTab("Volume", null, volume, "Volume units");
    add(tPane);

    // Panel --end.
}

public static void main(String[] args) {

    TestingGround app = new TestingGround();
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.pack();
    app.setVisible(true);

}

}

GridBagConstraints helper class is taken from Cay Horstmann's and Gary Cornell's Core Java and can be found here: http://www.horstmann.com/articles/GBC.java.

I managed to figure out from Gagandeep's example that panels can be put on top of, let's call it a mother-panel. This way each of child-panels can have its own border.

Second thing: I decided to use GridBagLayout, as it seems to be the most accurate to be used in this and further projects of mine. Well, I still have to learn a lot about it (for example, in order to make the components aligned to some lines ;-) [edit: just added setPreferredSize() to JComboBoxes; makes the layout better-looking ;-)]).

Thank you Everyone for help and valuable hints!

The application after correction.

Share:
45,462
AbreQueVoy
Author by

AbreQueVoy

Daily: a corporation employee. After work: self-taught Java/Android programmer. Hobby: travelling.

Updated on October 13, 2020

Comments

  • AbreQueVoy
    AbreQueVoy over 3 years

    I'm building an application which will consist of few tabbed panels. On each of them, I'd like to put sets of components separated from each other by borders. It would look like:

    |- Titled Border 1 ---
    
    [JTextField] [JComboBox] [JTextField] [JComboBox]
    
    |--------
    
    |- Titled Border 2 ---
    
    [JTextField] [JComboBox] [JTextField] [JComboBox]
    
    |--------
    
    ... and so forth.
    

    When I tried to simply add new border, Titled Border 2, to the panel, it was added and covered the first one leaving components on top though. In some examples I saw many JPanels defined within one frame and each panel had its own border. It might work in my case but how to add these panels to be displayed within one tab?

    One of Oracle's tutorials shows exactly a tabbed pane with demo of many kinds of borders. When I tried to edit it and put a component there, it appeared between two borders instead of being surrounded. And it was another option that was unsuccessful for me.

    Second thing is, I don't use any layout manager, components positions are fixed and honestly I would keep this setting. Or maybe you recommend using any layout manager in this specific case?

    Would you have any hints on how to solve this problem?

    Edit: it seems I'm not allowed yet to attach a screenshot, but here's the part of code taking care of displaying the borders:

        lenMicro = new JPanel();
        lenMicro.setLayout(null);
    
        bGreyLine = BorderFactory.createLineBorder(Color.GRAY, 1, true);
        bTitled1 = BorderFactory.createTitledBorder(bGreyLine, "Length (1/2)", TitledBorder.LEFT, TitledBorder.TOP);
        lenMicro.setBorder(bTitled1);
        bTitled2 = BorderFactory.createTitledBorder(bGreyLine, "Length (2/2)", TitledBorder.LEFT, TitledBorder.TOP);
        lenMicro.setBorder(bTitled2); 
    

    The border titled "Length (2/2)" is displayed when the last two lines are uncommented.

  • AbreQueVoy
    AbreQueVoy over 11 years
    Thanks a lot! It helped me to understand how things are going in this matter. I decided to use a layout manager, GridBagLayout, and now I'm dealing with settings of it. When I'm done, I'll publish the most relevant parts of code.
  • nIcE cOw
    nIcE cOw over 11 years
    Sure sure ask anything, that might can give you trouble, Layouts are always good. For the rest You're MOST WELCOME and KEEP SMILING :-) An SSCCE to work on, will still be much appreciated
  • nIcE cOw
    nIcE cOw over 11 years
    Just a word of advice, always use calls like frame.setVisible(true/false), after adding everything to the JFrame, not before that. That way it presents itself to the view, once it has realized it's size. As done by you, it might can give abnormal results sometimes, by calling visible property much before the frame has actually calculated it's size. +1 though for the effort you had given into this :-)
  • AbreQueVoy
    AbreQueVoy over 11 years
    OK, thanks for advice! (I'll have to talk to my teacher then, ha ha :-))