Wie werden Komponenten mit Rändern versehen?

Java bietet durch das Interface Border und die Klasse BorderFactory die Möglichkeit, Swing-Komponenten mit Rändern und sogar Abständen zu versehen.

Anwendung

Alle von JComponent abgeleiteten Komponenten haben einen oder sogar mehrere Ränder, die nach eigenen Vorstellungen konfiguriert oder auch entfernt werden können. Sie bestimmen die Erscheinung der gezeichneten Kanten und Ecken. Mehrere Ränder können miteinander kombiniert werden oder auch einen unsichtbaren Leerraum definieren, der den Abstand nach außen oder innen bestimmt.

Das Hinzufügen einer Border findet durch die Methode JComponent#setBorder() statt und kann auf jede von JComponent abgeleitete Komponente angewendet werden.
Oracle empfiehlt das direkte Zuweisen einer selbst definierten Border jedoch nur für JLabel und JPanel. Für alle anderen Komponenten wird geraten, diese in ein JPanel einzubetten und den Rand statt dessen diesem zuzuweisen.1

Der folgende Quelltext erzeugt die unten als Beispiele gezeigten Fenster. An der Stelle der Kommentare  // Border und // Labeltext muss dabei das unter der jeweiligen Abbildung gezeigte Quelltextfragment eingetragen werden.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;

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

public class Borders {

    public Borders() {
        init();
    }
    
    private void init() {
        GridLayout gl = new GridLayout(1,1);
        JPanel outerPanel = new JPanel(gl);
        outerPanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
        JPanel innerPanel = new JPanel(gl);
        innerPanel.setPreferredSize(new Dimension(450, 100));
        outerPanel.add(innerPanel);
        JLabel label = new JLabel();
        label.setHorizontalAlignment(SwingConstants.CENTER);
        innerPanel.add(label);
        innerPanel.setBorder(
             // Border
        );
        label.setText("<html>"
                + // Labeltext
                + "</html>");
        JFrame frame = new JFrame();
        frame.setContentPane(outerPanel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setTitle("Borders");
		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Borders());
    }
}

Erzeugung von Border-Objekten

Ein Border-Objekt kann auf zweierlei Weise erzeugt werden:

Worin besteht der Unterschied? Das sichtbare Ergebnis ist in beiden Fällen das gleiche. Tatsächlich scheint der Grund für diese Doppelung eher ein historischer zu sein: Wärend bei Nutzung der Konstruktoren jedes Mal ein neues Objekt erzeugt wird, speichert BorderFactory einige der einfachen Border-Objekte als Konstanten, um bei häufiger Verwendung Speicherplatz zu sparen:

public class BorderFactory {
    static final Border sharedRaisedBevel = new BevelBorder(0);
    static final Border sharedLoweredBevel = new BevelBorder(1);
    private static Border sharedSoftRaisedBevel;
    private static Border sharedSoftLoweredBevel;
    static final Border sharedEtchedBorder = new EtchedBorder();
    private static Border sharedRaisedEtchedBorder;
    static final Border emptyBorder = new EmptyBorder(0, 0, 0, 0);
    private static Border sharedDashedBorder;
    //...
}

Der Einheitlichkeit halber wird bei den folgenden Beispielen ausschließlich BorderFactory.createXXXBorder() verwendet.

Beispiele

Abstände durch EmptyBorder

Eine EmptyBorder definiert einen Leerraum zwischen der äußeren Grenze der Komponente und ihrem Inhalt und ist somit hervorragend geeignet, Abstände einzurichten. Sie können dem Konstruktor für alle vier Positionen getrennt in der folgenden Reihenfolge übergeben werden: oben, links, unten, rechts.

Abbildung: createEmptyBorder(5, 25, 40, 60)
BorderFactory.createEmptyBorder(5, 25, 40, 60)

Müssen die genauen Abstände einer EmptyBorder ermittelt werden, so können die Insets der EmptyBorder durch deren Methode getBorderInsets() zurückgegeben werden. Die beiden folgenden Abbildungen verdeutlichen die Eigenschaften einer EmptyBorder durch Setzen eines farbigen Hintergrundes des Labels.

Abbildung: createEmptyBorder(5, 25, 40, 60)
BorderFactory.createEmptyBorder(5, 25, 40, 60)
Abbildung: createEmptyBorder()
BorderFactory.createEmptyBorder()

Einfache Ränder

Abbildung: createLineBorder(Color.RED) Abbildung: createLineBorder(Color.RED)
BorderFactory.createLineBorder(Color.RED)
Abbildung: createLineBorder(Color.BLUE, 10) Abbildung: createLineBorder(Color.BLUE, 10)
BorderFactory.createLineBorder(Color.BLUE, 10)
Abbildung: createLineBorder(Color.BLACK, 20, true) Abbildung: createLineBorder(Color.BLACK, 20, true)
BorderFactory.createLineBorder(Color.BLACK, 20, true)
Abbildung: createEtchedBorder(EtchedBorder.RAISED) Abbildung: createEtchedBorder(EtchedBorder.RAISED)
BorderFactory.createEtchedBorder(EtchedBorder.RAISED)
Abbildung: createEtchedBorder(EtchedBorder.LOWERED) Abbildung: createEtchedBorder(EtchedBorder.LOWERED)
BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)
Abbildung: createEtchedBorder(EtchedBorder.LOWERED, Color.RED, Color.GREEN) Abbildung: createEtchedBorder(EtchedBorder.LOWERED, Color.RED, Color.GREEN)
BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.RED, Color.GREEN)
Abbildung: createBevelBorder(BevelBorder.RAISED) Abbildung: createBevelBorder(BevelBorder.RAISED)
BorderFactory.createBevelBorder(BevelBorder.RAISED)
Abbildung: createBevelBorder(BevelBorder.LOWERED) Abbildung: createBevelBorder(BevelBorder.LOWERED)
BorderFactory.createBevelBorder(BevelBorder.LOWERED)
Abbildung: createSoftBevelBorder(BevelBorder.LOWERED, Color.CYAN, Color.BLUE, Color.LIGHT_GRAY, Color.DARK_GRAY) Abbildung: createSoftBevelBorder(BevelBorder.LOWERED, Color.CYAN, Color.BLUE, Color.LIGHT_GRAY, Color.DARK_GRAY)
BorderFactory.createSoftBevelBorder(BevelBorder.LOWERED, Color.CYAN, Color.BLUE, Color.LIGHT_GRAY, Color.DARK_GRAY)
Abbildung: createMatteBorder(5, 10, 15, 20, Color.CYAN) Abbildung: createMatteBorder(5, 10, 15, 20, Color.CYAN)
BorderFactory.createMatteBorder(5, 10, 15, 20, Color.CYAN)

Ränder mit Titel (TitledBorder)

Abbildung: createTitledBorder('Ein Titel') Abbildung: createTitledBorder('Ein Titel')
BorderFactory.createTitledBorder("Ein Titel")
Abbildung: createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel") Abbildung: createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel")
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel")
Abbildung: createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel%quot;) Abbildung: createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel")
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.ORANGE), "Ein Titel", TitledBorder.RIGHT, TitledBorder.ABOVE_BOTTOM, new Font("Garamond", Font.BOLD, 12), Color.GREEN)

Zusammengesetzte Ränder (CompoundBorder)

Eine CompoundBorder besteht aus zwei beliebigen, getrennt definierten Border-Objekten. Da sie ihrerseits wiederum aus CompoundBorder-Objekten bestehen können, ist eine Fülle an Kombinationsmöglichkeiten gegeben.

Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 25, true)) Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 25, true))
BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 25, true))
Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 25, true)) Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 5, true))
BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 5, true))
Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 25, true) Abbildung: createCompoundBorder(BorderFactory.createLineBorder(Color.GREEN, 35), BorderFactory.createLineBorder(Color.MAGENTA, 5, true)
BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(3, 6, 9, 12, Color.BLUE), BorderFactory.createLineBorder(Color.YELLOW)), BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.MAGENTA, 5, true), BorderFactory.createBevelBorder(BevelBorder.RAISED)))
Abbildung: BorderFactory.createCompoundBorder(
                BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(3, 6, 9, 12, Color.BLUE),
                        BorderFactory.createEmptyBorder(15, 10, 5, 0)),
                BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.MAGENTA, 5, true),
                        BorderFactory.createBevelBorder(BevelBorder.RAISED))) Abbildung: BorderFactory.createCompoundBorder(
                BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(3, 6, 9, 12, Color.BLUE),
                        BorderFactory.createEmptyBorder(15, 10, 5, 0)),
                BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.MAGENTA, 5, true),
                        BorderFactory.createBevelBorder(BevelBorder.RAISED)))
BorderFactory.createCompoundBorder( BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(3, 6, 9, 12, Color.BLUE), BorderFactory.createEmptyBorder(15, 10, 5, 0)), BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(Color.MAGENTA, 5, true), BorderFactory.createBevelBorder(BevelBorder.RAISED)))
Quellen
  1. https://docs.oracle.com/javase/tutorial/uiswing/components/border.html