Wie versieht man die Tabs eines JTabbedPane mit Komponenten?

Registerkarten können durch ein JTabbedPane erzeugt werden. Auf den Reitern, den Tabs, lassen sich auch Komponenten einbinden, die zur Steuerung von Funktion und/oder Inhalt der einzelnen Karten dienen können.

Eine JTabbedPane ähnelt einem aus der analogen Welt bekannten Satz Karteikarten mit Reitern, den Tabs. Bei Auswahl eines Tabs wird die zugehörige "Karte", die Pane, sichtbar. Sie dient als Container und kann eine beliebige Komponente enthalten. Durch Aktivierung unterschiedlicher Tabs können somit verschiedene Komponenten an gleicher Stelle sichtbar gesetzt werden.

Eine einfache JTabbedPane

Ein Fenster mit einfachem JTabbedPane

In der durch die Konstruktoren vorgegebenen Form weisen Tabs einen Titel und/oder ein Icon auf, während die dazugehörige Pane eine oder mehrere, in einem JPanel gruppierte Komponenten enthalten kann.
Tabs werden intern durch einen bei 0 beginnenden Index repräsentiert, der bei einer ganzen Reihe an Methoden als Argument Verwendung findet.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

public class SimpleTabbedPane {

    private static final int NUM_TABS = 6;

    public SimpleTabbedPane() {
        init();
    }

    private void init() {
        JTabbedPane tp = new JTabbedPane();
        tp.setPreferredSize(new Dimension(400, 150));
        for (int i = 0; i < NUM_TABS; i++) {
            tp.addTab("Tab " + (i + 1), makePanel("Beispieltext " + (i + 1)));
        }
        JFrame frame = new JFrame("TabbedPane-Beispiel");
        frame.add(tp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JComponent makePanel(String txt) {
        JComponent panel = new JPanel(new GridLayout(1, 1));
        JLabel label = new JLabel(txt);
        panel.add(label);
        return panel;
    }

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

Das Eingangsbeispiel erzeugt ein Fenster mit einer einfachen JTabbedPane. Sie weist sechs Tabs auf, die in der Methode init() innerhalb einer Schleife initialisiert und durch addTab() in Zeile 24 dem JTabbedPane hinzugefügt werden. Die dreifach überladene Methode addTab() erhält in diesem Fall als ersten Parameter den Titeltext des Tabs und als zweiten ein JPanel mit Label übergeben. Es wird in der Methode makePanel() erzeugt. Das Panel wird im dem jeweilegen Tab zugehörigen Pane geladen.
Es muss erwähnt werden, dass dem JTabbedPane hier in Zeile 22 eine bevorzugte Größe zugewiesen wird, da es sonst bei Verwendung von JFrame#pack() auf die Breite des im Pane geladenen JLabel kollabieren würde.

Eine Komponente im Tab

Nicht nur die Panes, auch die Tabs selbst können mit Komponenten versehen werden. Dies geschieht mit Hilfe der Methode JTabbedPane#setTabComponentAt(int index, Component component). Das folgende Beispiel demonstriert dies durch Erzeugung eines Tabs mit JTextField und eines Tabs mit einem Button, mit dem die Aktivität der anderen Tabs blockiert werden kann.

Eine JTabbedPane mit Komponenten in Tabs

Auf Tab 3 (mit dem Index 2) wird eine Instanz der Klasse ButtPanel geladen. Sie zeigt einen mit Titel und Icon versehenen JToggleButton, der bei einem ItemListener angemeldet ist (Zeile 22). Er wechselt bei Aktivierung des Buttons den Buttontext und steuert über die Methode handleButton() (Zeile 105) die Aktivität aller Tabs, indem diese über setEnabledAt() aktiviert oder deaktiviert werden.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingUtilities;

public class TabbedPaneMitKompImHeader {

    private static final int LOCK_TAB = 2;
    private static final int FIELD_TAB = 3;
    private static final int NUM_TABS = 6;

    public TabbedPaneMitKompImHeader() {
        init();
    }

    private void init() {
        JTabbedPane tp = new JTabbedPane();
        tp.setPreferredSize(new Dimension(480, 150));
        for (int i = 0; i < NUM_TABS; i++) {
            tp.addTab("Tab " + (i + 1), makeTab("Beispieltext " + (i + 1)));
            if (i == LOCK_TAB) {
                tp.setTabComponentAt(i, new ButtPanel(tp, i));
            }
            if (i == FIELD_TAB) {
                JTextField field = new JTextField(5);
                tp.setTabComponentAt(i, field);
                field.addKeyListener(new KeyAdapter() {
                    @Override
                    public void keyReleased(KeyEvent e) {
                        ((JLabel) ((JPanel) tp.getComponentAt(FIELD_TAB)).getComponent(0)).setText(field.getText());
                    }
                });
            }
        }
        JFrame frame = new JFrame("TabbedPane-Beispiel");
        frame.add(tp, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private JComponent makeTab(String txt) {
        JComponent panel = new JPanel(new GridLayout(1, 1));
        JLabel label = new JLabel(txt);
        panel.add(label);
        return panel;
    }

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

class ButtPanel extends JPanel {
    private static final String ACTIVATE_TABS = "Tabs aktivieren";
    private static final String DEACTIVATE_TABS = "Tabs sperren";
    private static final String LOCK_ICON_PATH = "/img/lock.png";
    private static final String UNLOCK_ICON_PATH = "/img/unlock.png";
    private JTabbedPane tp;

    public ButtPanel(JTabbedPane tp, int tabIndex) {
        this.tp = tp;
        this.setBorder(null);
        this.setLayout(new BorderLayout());
        this.add(createTB());
    }

    private JToggleButton createTB() {
        final ImageIcon lockIi = loadImage(LOCK_ICON_PATH);
        final ImageIcon unlockIi = loadImage(UNLOCK_ICON_PATH);
        final JToggleButton tb = new JToggleButton(DEACTIVATE_TABS);
        Font f = tb.getFont();
        tb.setFont(new Font(f.getName(), f.getStyle(), f.getSize() + 2));
        tb.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent ie) {
                handleButton(((JToggleButton) ie.getSource()).isSelected());
                tb.setText(tb.isSelected() ? ACTIVATE_TABS : DEACTIVATE_TABS);
            }
        });
        if (lockIi != null && unlockIi != null) {
            tb.setIcon(unlockIi);
            tb.setSelectedIcon(lockIi);
        }
        return tb;
    }

    private void handleButton(boolean selected) {
        for (int i = 0; i < tp.getTabCount(); i++) {
            tp.setEnabledAt(i, !selected);
        }
    }

    private ImageIcon loadImage(String path) {
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(getClass().getResource(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ImageIcon(bi);
    }
}
            

Tab 4 (Index 3) enthält ein JTextField, dem ein KeyListener hinzugefügt wurde (Zeile 44). Er registriert das Loslassen einer Taste und setzt den im Textfeld eingegebenen Text auf das im zugehörigen Pane geladene JLabel. Hierzu muss zunächst die im Pane primär geladene Komponente, im vorliegenden Fall ein JPanel, durch JTabbedPane#getComponentAt(int index) ermittelt werden. Da das gefragte JLabel die einzige auf dem Panel vorhandene Komponente ist, kann es durch getComponent(0) angesprochen werden (Zeile 47).

Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.