Search code examples
javaswingborder

COMPOUND BORDER : Get a outline border with title outside the Jpanel in java Swing


My only problem is that I don't know how to put my border outside the panel. I've tried compound and some other border code but so far I am unable to put it outside. It either disappears or it doesn't change at all.

The output that I want:

EXPECTED OUTPUT

The output that I'm getting :

CURRENT OUTPUT

I'm a newbie at swing and I have been searching and found out about compound border but I am still not so familiar on how it works with adding the buttons into the panel. (I've removed the code of me trying to do compound border because it was just a mess full of errors)

THE CODE :

package activityswing;

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


public class swing {
public static void main (String args []) {
     JFrame pa= new JFrame("Swing Activity");
        //boarder
        pa.setLayout(new BorderLayout());
        //panels
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
            //buttons
        JButton button1 = new JButton("Button 1");
        JButton button2 = new JButton("Button 2");
        JButton button3 = new JButton("Button 3");
        JButton button4 = new JButton("Button 4");
        JButton button5 = new JButton("Button 5");
        JButton button6 = new JButton("Button 6");

        //label
        JLabel lb1= new JLabel("Panel 1");
        JLabel lb2= new JLabel("Panel 2");

        //adding label to panel
        lb1.add(panel1);
        lb1.add(panel2);

        //panel1
        Border line1 = BorderFactory.createLineBorder(Color.blue);
        panel1.setBorder(line1);
        panel1.add(button1);
        panel1.add(button2);
        panel1.add(button3);
        panel1.setBorder(BorderFactory.createTitledBorder("Panel 1"));
        panel1.setBackground(Color.BLUE);
        panel1.setPreferredSize(new Dimension(270,40));

        //panel2
        Font font2 = new Font("Verdana",Font.ITALIC,12);
        Border line2 = BorderFactory.createLineBorder(Color.blue);
        lb2.setFont(font2);
        panel2.setBorder(line2);
        LayoutManager layout = new FlowLayout();  
        panel2.setLayout(layout);
        panel2.add(button4);
        panel2.add(button5);
        panel2.add(button6);
        panel2.add(lb2);
        panel2.setBorder(BorderFactory.createTitledBorder("Panel 2"));
        panel2.setBackground(Color.GREEN);
        panel2.setPreferredSize(new Dimension(270,40));

        //FRAME
        FlowLayout flow = new FlowLayout(FlowLayout.CENTER, 50,50);
        pa.setLayout(flow);
        pa.pack();
        pa.add(panel1);
        pa.add(panel2);
        pa.setSize(700,200);
        pa.setResizable(false);
        pa.setVisible(true);
        pa.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pa.setLocationRelativeTo(null);

}
}

Solution

  • Don't add component to labels

    lb1.add(panel1);
    lb1.add(panel2);
    

    Labels calculate their preferred size based the label properties (text/icon/font/etc) and not the child components.

    Don't mess with the preferredSize of the components unless you are absolutely certain you willing to take over all the responsibility to calculate the components size.

    The simple solution would be to create a instance of TitledBorder yourself, for example...

    Font font2 = new Font("Verdana", Font.ITALIC, 12);
    TitledBorder border = new TitledBorder("Panel 1");
    border.setTitleFont(font2);
    

    I'd kind of tempted to create a factory method to make this easier, but you get the general idea

    To get the border "separated" from the component, I would use a compound component approach, where the outer panel contains the title and then add the inner panel into it.

    If needed, you could use CompoundBorder and use a EmptyBorder on the side of the outer panel

    Have a look at:

    ... for more details

    Simple

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.LayoutManager;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.border.TitledBorder;
    
    public class Test {
    
        public static void main(String args[]) {
            JFrame pa = new JFrame("Swing Activity");
            //boarder
            pa.setLayout(new BorderLayout());
            //panels
            JPanel panel1 = new JPanel();
            JPanel panel2 = new JPanel();
            //buttons
            JButton button1 = new JButton("Button 1");
            JButton button2 = new JButton("Button 2");
            JButton button3 = new JButton("Button 3");
            JButton button4 = new JButton("Button 4");
            JButton button5 = new JButton("Button 5");
            JButton button6 = new JButton("Button 6");
    
            Font font2 = new Font("Verdana", Font.ITALIC, 12);
            TitledBorder border1 = new TitledBorder("Panel 1");
            border1.setTitleFont(font2);
            
            JPanel outter1 = new JPanel(new BorderLayout());
            outter1.setBorder(border1);
            panel1.add(button1);
            panel1.add(button2);
            panel1.add(button3);
            panel1.setBackground(Color.BLUE);
            outter1.add(panel1);
    
            //panel2
            LayoutManager layout = new FlowLayout();
            TitledBorder border2 = new TitledBorder("Panel 2");
            JPanel outter2 = new JPanel(new BorderLayout());
            outter2.setBorder(border2);
            
            panel2.setLayout(layout);
            panel2.add(button4);
            panel2.add(button5);
            panel2.add(button6);
            panel2.setBackground(Color.GREEN);
            
            outter2.add(panel2);
    
            //FRAME
            FlowLayout flow = new FlowLayout(FlowLayout.CENTER, 50, 50);
            pa.setLayout(flow);
            pa.add(outter1);
            pa.add(outter2);
            pa.pack();
            pa.setLocationRelativeTo(null);
            pa.setVisible(true);
            pa.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            pa.setLocationRelativeTo(null);
    
        }
    }