How do I create a simple JTabbedPane?

In this example you will learn how to use JTabbedPane to arrange some components in tabbed view. The JTabbedPane component of the Swing API allows some components such as panels to share the same view. By selecting the corresponding tab, the panel will be displayed on the user’s screen. To add tabs to the JTabbedPane class you can use the addTab() method.

To the addTab() method accept two arguments, the title of the tab and the component you wish to display as the content of the tab. In the code snippet below we will use a simple panel as the content of the tab. You can also define an image icon for the tab which makes the program looks better. You can read it in this example:

Now, let’s create a simple example of JTabbedPane which has three tabs and the corresponding content, they are the Dashboard, Transaction and Account tabs. Below is an image that show how the screen will look.

Simple JTabbedPane Demo

package org.kodejava.swing;

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

public class SimpleTabbedPane extends JPanel {
    public SimpleTabbedPane() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new SimpleTabbedPane();
        panel.setOpaque(true);

        JFrame frame = new JFrame("Simple Tabbed Pane Demo");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SimpleTabbedPane::showFrame);
    }

    private void initializeUI() {
        JTabbedPane tabbedPane = new JTabbedPane();

        JPanel dashboardPanel = new JPanel();
        dashboardPanel.add(new JLabel("Dashboard"));

        // Add Dashboard Tab
        tabbedPane.addTab("Dashboard", dashboardPanel);

        JPanel transactionPanel = new JPanel();
        transactionPanel.add(new JLabel("Transaction"));

        // Add Transactions Tab
        tabbedPane.addTab("Transaction", transactionPanel);

        JPanel accountPanel = new JPanel();
        accountPanel.add(new JLabel("Account"));

        // Add Account Tab
        tabbedPane.addTab("Account", accountPanel);

        this.setLayout(new BorderLayout());
        this.setPreferredSize(new Dimension(500, 200));
        this.add(tabbedPane, BorderLayout.CENTER);
    }
}

How do I reverse JSlider’s value-range?

On a normal JSlider the value range displayed left-to-right on a horizontal JSlider and bottom-to-top on vertical JSlider. To reverse the slider values from their normal order you can use the setInverted() method of the JSlider instance. Passing a true boolean value into this method call reverse the values order.

package org.kodejava.swing;

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

public class JSliderInvertedDemo extends JPanel {
    public JSliderInvertedDemo() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new JSliderInvertedDemo();

        JFrame frame = new JFrame("Inverted JSlider");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JSliderInvertedDemo::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 200));

        JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 20, 10);
        slider.setMinorTickSpacing(1);
        slider.setMajorTickSpacing(5);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);

        // Reverse the value-range of a JSlider. On a normal
        // horizontal JSlider the maximum value is on the right
        // side. Specifying inverted to true makes the maximum
        // value placed on the left side.
        slider.setInverted(true);

        add(slider, BorderLayout.CENTER);
    }
}

The result of the code snippet above is:

Inverted JSlider Demo

How do I create a JSlider with custom labels?

The JSlider‘s setLabelTable() method allows you to define a custom labels for the JSlider. The label table is a Hashtable that contains an Integer number as the keys and a JLabel component as their values. The integer keys correspond to the JSlider tick where the labels will be customized.

package org.kodejava.swing;

import javax.swing.*;
import java.awt.*;
import java.util.Hashtable;

public class JSliderCustomLabel extends JPanel {
    public JSliderCustomLabel() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new JSliderCustomLabel();

        JFrame frame = new JFrame("JSlider Custom Label");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JSliderCustomLabel::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 200));

        JSlider slider = new JSlider(JSlider.VERTICAL, 0, 40, 0);
        slider.setMinorTickSpacing(1);
        slider.setMajorTickSpacing(5);
        slider.setPaintTicks(true);

        Hashtable<Integer, JLabel> labels = new Hashtable<>();
        labels.put(0, new JLabel("Freezing"));
        labels.put(15, new JLabel("Cold"));
        labels.put(25, new JLabel("Warm"));
        labels.put(35, new JLabel("Hot"));
        slider.setLabelTable(labels);

        slider.setPaintLabels(true);

        add(slider, BorderLayout.CENTER);
    }
}

The screen capture of the example above is:

JSlider with Custom Labels Demo

How do I create a JSlider that snap to the closest tick mark?

The JSlider‘s setSnapToTicks() method call is used to move JSlider‘s knob to the nearest tick mark from where you positioned the knob. The default value of this property is false. To make it snap to the closest tick set this property to true.

package org.kodejava.swing;

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

public class SnapToTickJSlider extends JPanel {
    public SnapToTickJSlider() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new SnapToTickJSlider();

        JFrame frame = new JFrame("JSlider - Snap to Tick");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SnapToTickJSlider::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 200));

        JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 30, 0);
        slider.setMinorTickSpacing(5);
        slider.setMajorTickSpacing(10);
        slider.setPaintLabels(true);
        slider.setPaintTicks(true);

        // Snaps to the closest tick mark next to where the user
        // positioned the knob.
        slider.setSnapToTicks(true);

        add(slider, BorderLayout.CENTER);
    }
}

The screen capture of the result of the code snippet above is:

JSlider Snap to Ticks Demo

How do I create a vertical JSlider?

To create a vertical JSlider set the orientation on the JSlider‘s constructor to JSlider.VERTICAL. If you do not pass JSlider.VERTICAL as a constructor parameter use the setOrientation() method instead.

package org.kodejava.swing;

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

public class JSliderVertical extends JPanel {
    public JSliderVertical() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new JSliderVertical();
        panel.setOpaque(true);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setTitle("Vertical JSlider");
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JSliderVertical::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 200));

        // Creates a vertical JSlider that accept value in the
        // range between 0 and 20. The initial value is set to 4.
        JSlider slider = new JSlider(JSlider.VERTICAL, 0, 20, 4);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        slider.setMinorTickSpacing(1);
        slider.setMajorTickSpacing(4);

        add(slider, BorderLayout.CENTER);
    }
}

The screen capture of the code snippet above.

Vertical JSlider Demo

How do I use a JSlider component?

This simple example show you how to use the JSlider component. A JSlider component is intended to let the user easily enter a numeric value bounded by a minimum and maximum value.

There are a couples properties that you need to set when creating a JSlider. These include setting setMinorTickSpacing(), setMajorTickSpacing(), setPaintTicks() and setPaintLabels(). These methods set the minor tick spacing, major tick spacing, display the ticks and the tick labels.

To get the selected value from JSlider we need to implements the stateChanged() method defined in the ChangeListener interface and then pass the listener to the JSlider by calling the addChangeListener() method.

package org.kodejava.swing;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

public class JSliderDemo extends JPanel implements ChangeListener {
    private JTextField field;

    public JSliderDemo() {
        initializeUI();
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 200));

        // Creates an instance of JSlider with a horizontal
        // orientation. Define 0 as the minimal value and
        // 50 as the maximum value. The initial value is set
        // to 10.
        JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 50, 10);

        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        slider.setMinorTickSpacing(1);
        slider.setMajorTickSpacing(10);

        slider.addChangeListener(this);

        JLabel label = new JLabel("Selected Value:");
        field = new JTextField(5);

        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout());
        panel.add(label);
        panel.add(field);

        add(slider, BorderLayout.NORTH);
        add(panel, BorderLayout.SOUTH);
    }

    public void stateChanged(ChangeEvent e) {
        JSlider slider = (JSlider) e.getSource();

        // Get the selection value of JSlider
        field.setText(String.valueOf(slider.getValue()));
    }

    public static void showFrame() {
        JPanel panel = new JSliderDemo();
        panel.setOpaque(true);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setTitle("JSlider Demo");
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JSliderDemo.showFrame();
            }
        });
    }
}

Below is the result of the code snippet above.

JSlider Demo

How do I create a scrollable JTable component?

To create a scrollable JTable component we have to use a JScrollPane as the container of the JTable. Besides, that we also need to set the table auto resize mode to JTable.AUTO_RESIZE_OFF so that a horizontal scroll bar displayed by the scroll pane when needed. If we do not turn off the auto resize mode, the columns of the table will be resized to fit the available window size.

package org.kodejava.swing;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Dimension;

public class ScrollableJTable extends JPanel {
    public ScrollableJTable() {
        initializeUI();
    }

    private static void showFrame() {
        JPanel panel = new ScrollableJTable();
        panel.setOpaque(true);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setTitle("Scrollable JTable");
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(ScrollableJTable::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 250));

        JTable table = new JTable(20, 20);

        // Turn off JTable's auto resize so that JScrollPane will show a horizontal
        // scroll bar.
        table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        JScrollPane pane = new JScrollPane(table);
        add(pane, BorderLayout.CENTER);
    }
}

Below is the result of the code snippet above.

Scrollable JTable Component Demo

Scrollable JTable Component Demo

How do I programmatically select JTable’s columns?

This program shows you how to select some columns in the JTable programmatically. Below we demonstrates how to select columns using the setColumnSelectionInterval() method, remove or clear column selection using removeColumnSelectionInterval() method and use the addColumnSelectionInterval() to add more columns to the previously selected columns.

package org.kodejava.swing;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;

public class JTableColumnSelectProgrammatically extends JPanel {
    public JTableColumnSelectProgrammatically() {
        initializePanel();
    }

    public static void showFrame() {
        JPanel panel = new JTableColumnSelectProgrammatically();
        panel.setOpaque(true);

        JFrame frame = new JFrame("JTable Column Selection");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JTableColumnSelectProgrammatically::showFrame);
    }

    private void initializePanel() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 500));

        final JTable table = new JTable(new MyTableModel());
        table.setFillsViewportHeight(true);
        JScrollPane pane = new JScrollPane(table);

        JLabel label1 = new JLabel("From col: ");
        final JTextField field1 = new JTextField(3);
        JLabel label2 = new JLabel("To col: ");
        final JTextField field2 = new JTextField(3);
        JButton select = new JButton("Select");
        JButton clear = new JButton("Clear");
        JButton add = new JButton("Add another one");

        // Enables column selection mode and disable row
        // selection mode.
        table.setColumnSelectionAllowed(true);
        table.setRowSelectionAllowed(false);

        // Select columns based on the input.
        select.addActionListener(event -> {
            int index1 = 0;
            int index2 = 0;
            try {
                index1 = Integer.parseInt(field1.getText());
                index2 = Integer.parseInt(field2.getText());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }

            if (index1 <= 0 || index2 <= 0 ||
                    index1 > table.getColumnCount() ||
                    index2 > table.getColumnCount()) {
                JOptionPane.showMessageDialog(table, "Selection out of range!");
            } else {
                table.setColumnSelectionInterval(index1 - 1, index2 - 1);
            }
        });

        // Clears column selection
        clear.addActionListener(e -> {
            table.removeColumnSelectionInterval(0, table.getColumnCount() - 1);
            field1.setText("");
            field2.setText("");
        });

        // Add one more column after the last selected column.
        add.addActionListener(event -> {
            int index2 = 0;
            try {
                index2 = Integer.parseInt(field2.getText());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }

            index2 = index2 + 1;
            if (index2 <= table.getColumnCount()) {
                table.addColumnSelectionInterval(index2 - 1, index2 - 1);
                field2.setText(String.valueOf(index2));
            }
        });

        JPanel command = new JPanel(new FlowLayout());
        command.add(label1);
        command.add(field1);
        command.add(label2);
        command.add(field2);
        command.add(select);
        command.add(clear);
        command.add(add);

        add(pane, BorderLayout.CENTER);
        add(command, BorderLayout.SOUTH);
    }

    public static class MyTableModel extends AbstractTableModel {
        private final String[] columns = {"ID", "NAME", "AGE", "A STUDENT?"};
        private final Object[][] data = {
                {1, "Alice", 20, Boolean.FALSE},
                {2, "Bob", 10, Boolean.TRUE},
                {3, "Carol", 15, Boolean.TRUE},
                {4, "Mallory", 25, Boolean.FALSE}
        };

        public int getRowCount() {
            return data.length;
        }

        public int getColumnCount() {
            return columns.length;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }

        // This method is used by the JTable to define the default
        // renderer or editor for each cell. For example if you have
        // a boolean data it will be rendered as a checkbox. A
        // number value is right aligned.
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return data[0][columnIndex].getClass();
        }
    }

}

Below is the screen capture of the program.

Programmatically Select JTable Column

Programmatically Select JTable Column

How do I right-align numbers data in JTable component?

To right-align numbers type of data in JTable cells we need to implements a TableModel. The TableModel‘s interface getColumnClass(int index) implementation return the class of the cell values, this information is used by JTable component to setup a default renderer and editor for the column.

package org.kodejava.swing;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;

public class JTableNumberRightAlign extends JPanel {
    public JTableNumberRightAlign() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new JTableNumberRightAlign();
        panel.setOpaque(true);

        JFrame frame = new JFrame("JTable Number Align");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JTableNumberRightAlign::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 500));

        JTable table = new JTable(new NumberTableModel());
        table.setFillsViewportHeight(true);

        JScrollPane pane = new JScrollPane(table);
        add(pane, BorderLayout.CENTER);
    }

    static class NumberTableModel extends AbstractTableModel {
        String[] columns = {"STUDENT ID", "NAME", "YEARS", "SCORE"};
        Object[][] data = {
                {"S001", "ALICE", 10, 8.75},
                {"S002", "BOB", 10, 7.50},
                {"S003", "CAROL", 10, 9.00},
                {"S004", "MALLORY", 10, 8.50}
        };

        public int getRowCount() {
            return data.length;
        }

        public int getColumnCount() {
            return columns.length;
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];
        }

        // This method is used by the JTable to define the default
        // renderer or editor for each cell. For example if you have
        // a boolean data it will be rendered as a checkbox. A
        // number value is right aligned.
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return data[0][columnIndex].getClass();
        }
    }
}

Here is the result of the program:

JTable Number Right Align

JTable Number Right Align

How do I render boolean value as checkbox in JTable component?

To make a JTable renders a boolean as a checkbox in the table cell we need to tell the table that a cell stores a boolean type of data. To do this we have to implement a TableModel for the JTable component.

TableModel‘s getColumnClass(int columnIndex) must return the type of data stored in a cell. When it returns that the column stored a Boolean data, JTable displays a checkbox as the default renderer or editor for that cell.

package org.kodejava.swing;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;

public class JTableBooleanAsCheckbox extends JPanel {
    public JTableBooleanAsCheckbox() {
        initializeUI();
    }

    public static void showFrame() {
        JPanel panel = new JTableBooleanAsCheckbox();
        panel.setOpaque(true);

        JFrame frame = new JFrame("JTable Boolean as Checkbox");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(JTableBooleanAsCheckbox::showFrame);
    }

    private void initializeUI() {
        setLayout(new BorderLayout());
        setPreferredSize(new Dimension(500, 500));

        JTable table = new JTable(new BooleanTableModel());
        table.setFillsViewportHeight(true);
        JScrollPane pane = new JScrollPane(table);
        add(pane, BorderLayout.CENTER);
    }

    static class BooleanTableModel extends AbstractTableModel {
        String[] columns = {"STUDENT ID", "NAME", "SCORE", "PASSED"};
        Object[][] data = {
                {"S001", "ALICE", 90.00, Boolean.TRUE},
                {"S002", "BOB", 45.50, Boolean.FALSE},
                {"S003", "CAROL", 60.00, Boolean.FALSE},
                {"S004", "MALLORY", 75.80, Boolean.TRUE}
        };

        public int getRowCount() {
            return data.length;
        }

        public int getColumnCount() {
            return columns.length;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];
        }

        @Override
        public String getColumnName(int column) {
            return columns[column];
        }

        // This method is used by the JTable to define the default
        // renderer or editor for each cell. For example if you have
        // a boolean data it will be rendered as a checkbox. A
        // number value is right aligned.
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return data[0][columnIndex].getClass();
        }
    }
}

Here is the result of the program:

JTable render Boolean as Checkbox

JTable render Boolean as Checkbox