Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Working with Swing Components: Spinners, Split Panes, Tabbed Panes, and Tables

Tech May 16 1

Using Spinners

A JSpinner is a composite component that allows a user to select a value from an ordered sequence, such as numbers or dates. It consists of a text field for displaying and editing the current value, and two small buttons (up and down arrows) for stepping through the sequence. Unlike a combo box, a spinner does not display a dropdown list of all possible values, making it suitable for sequences where the values are obvious or when the set of values is very large.

The sequence of values and the current value are managed by a SpinnerModel. Swing provides several standard models:

  • SpinnerListModel: For selecting from an array or List of objects.
  • SpinnerNumberModel: For selecting from a range of numbers with a defined step size.
  • SpinnerDateModel: For selecting from a range of dates, incrementing or decrementing a specific calendar field.

Here's an example of creating a spinner to select a time of day:

import javax.swing.*;
import java.awt.*;
import java.util.Calendar;
import java.util.Date;

public class TimeSpinnerDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Time Spinner Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());

        // Create a model for hours (0-23)
        SpinnerNumberModel hourModel = new SpinnerNumberModel(12, 0, 23, 1);
        JSpinner hourSpinner = new JSpinner(hourModel);
        hourSpinner.setEditor(new JSpinner.NumberEditor(hourSpinner, "00"));

        // Create a model for minutes (0-59)
        SpinnerNumberModel minuteModel = new SpinnerNumberModel(0, 0, 59, 1);
        JSpinner minuteSpinner = new JSpinner(minuteModel);
        minuteSpinner.setEditor(new JSpinner.NumberEditor(minuteSpinner, "00"));

        frame.add(new JLabel("Hour:"));
        frame.add(hourSpinner);
        frame.add(new JLabel("Minute:"));
        frame.add(minuteSpinner);

        frame.pack();
        frame.setVisible(true);
    }
}

Custom Spinners

You can create custom spinner models by extending AbstractSpinnerModel. For example, a model that cycles through a list of weekdays:

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

public class CyclingWeekdayModel extends SpinnerListModel {
    private final Object[] weekdays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    private int currentIndex = 0;

    public CyclingWeekdayModel() {
        super(new String[]{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"});
    }

    @Override
    public Object getNextValue() {
        currentIndex = (currentIndex + 1) % weekdays.length;
        return super.getList().get(currentIndex);
    }

    @Override
    public Object getPreviousValue() {
        currentIndex = (currentIndex - 1 + weekdays.length) % weekdays.length;
        return super.getList().get(currentIndex);
    }
}

Using Split Panes

A JSplitPane is a container that divides its space into two parts, either horizontal or vertically. The user can drag the divider to resize the two components. It's common to place each component inside a JScrollPane to allow scrolling if the content is larger than the available space.

Here's how to create a split pane with a text area and a list:

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

public class SplitPaneDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Split Pane Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout());

        // Create a text area
        JTextArea textArea = new JTextArea("This is the text area.");
        JScrollPane textScrollPane = new JScrollPane(textArea);

        // Create a list
        String[] data = {"Item 1", "Item 2", "Item 3", "Item 4", "Item 5"};
        JList<string> list = new JList<>(data);
        JScrollPane listScrollPane = new JScrollPane(list);

        // Create the split pane
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, listScrollPane, textScrollPane);
        splitPane.setOneTouchExpandable(true); // Adds one-touch expand buttons
        splitPane.setDividerLocation(150); // Initial divider location in pixels

        frame.add(splitPane, BorderLayout.CENTER);
        frame.setSize(400, 300);
        frame.setVisible(true);
    }
}</string>

Controlling the Split Pane

You can control the split pane's behavior using methods like setDividerLocation and setResizeWeight. The setResizeWeight method determines how extra space is distributed when the split pane is resized. A value of 0.5 gives equal weight to both components.

// Give equal weight to both components when the split pane is resized
splitPane.setResizeWeight(0.5f);

// Set the divider location to a specific pixel position
splitPane.setDividerLocation(200);

// Reset the divider to its preferred location
splitPane.resetToPreferredSizes();

Using Tabbed Panes

A JTabbedPane allows you to group multiple components (like panels) into a single container, with each component accessible via a tab. This is useful for organizing a complex user interface into manageable sections.

Here's an example of a tabbed pane with three tabs:

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

public class TabbedPaneDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Tabbed Pane Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);

        JTabbedPane tabbedPane = new JTabbedPane();

        // Create the first tab
        JPanel panel1 = new JPanel();
        panel1.add(new JLabel("This is the first tab."));
        tabbedPane.addTab("General", panel1);

        // Create the second tab
        JPanel panel2 = new JPanel();
        panel2.add(new JLabel("This is the second tab."));
        tabbedPane.addTab("Appearance", panel2);

        // Create the third tab
        JPanel panel3 = new JPanel();
        panel3.add(new JLabel("This is the third tab."));
        tabbedPane.addTab("Advanced", panel3);

        frame.add(tabbedPane);
        frame.setVisible(true);
    }
}

Custom Tab Components

You can customize the appearance of tabs by setting a custom component for each tab using setTabComponentAt. This allows you to add buttons, icons, or other UI elements to the tabs.

// Add a close button to the first tab
JButton closeButton = new JButton("X");
closeButton.addActionListener(e -> tabbedPane.removeTabAt(0));
tabbedPane.setTabComponentAt(0, closeButton);

Using Tables

A JTable displays data in a two-dimensional grid. It does not store the data itself; instead, it uses a TableModel to access the data. This follows the Model-View-Controller (MVC) design pattern.

Here's a basic example of creating a table with a custom model:

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

public class SimpleTableDemo {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Simple Table Demo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Define column names
        String[] columnNames = {"ID", "Name", "Price"};

        // Define data
        Object[][] data = {
            {1, "Product A", 19.99},
            {2, "Product B", 29.50},
            {3, "Product C", 9.99}
        };

        // Create a custom table model
        JTable table = new JTable(new AbstractTableModel() {
            @Override
            public int getRowCount() {
                return data.length;
            }

            @Override
            public int getColumnCount() {
                return columnNames.length;
            }

            @Override
            public Object getValueAt(int row, int col) {
                return data[row][col];
            }

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

            @Override
            public Class> getColumnClass(int columnIndex) {
                return getValueAt(0, columnIndex).getClass();
            }
        });

        // Add the table to a scroll pane
        JScrollPane scrollPane = new JScrollPane(table);
        frame.add(scrollPane);

        frame.pack();
        frame.setVisible(true);
    }
}

Custom Renderers and Editors

To customize how data is displayed or edited, you can provide custom TableCellRenderer and TableCellEditor implementations. For example, to render a Color value as a colored rectangle:

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

class ColorRenderer extends DefaultTableCellRenderer {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        if (value instanceof Color) {
            c.setBackground((Color) value);
            setText(""); // Clear text for a color cell
        }
        return c;
    }
}

You can then set this renderer for a specific column:

table.getColumnModel().getColumn(2).setCellRenderer(new ColorRenderer());

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.