[Java swing] Customize JTabbedPane

In my previous article introduced JTabbenPane some basic points, this article we learn a little more to Custom JTabbedPane better to let, like the picture below, have closed tab, More tab,…

Custom JTabbedPane

In which the most important is how we have to add new tab button, how each tab it close button tab. We will create 2 file, 1 implement custom file tab (there is JLabel title and tab close button tab) and 1 file created JTabbedPane Tab customized based on other files.

Getting new events added to the JTabbedPane tab


About creating a new tab button to add the substance we create 1 tab titled plus (“+”) and executed change event for JTabbedPane. Whenever click switch tab, if you click on this tab are performed more 1 new tab. Here is the code to create custom file JTabbedPane.

package nguyenvanquan7826.JTabbedPane;

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

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * --------------------- @author nguyenvanquan7826 ---------------------
 * ------------------ website: cachhoc.net -------------------
 * ---------- date: Jul 24, 2014 - filename: DemoCustomJTabPane.java ----------
 */
public class DemoCustomJTabbedPane extends JFrame {
	JTabbedPane tabbedPane;
	int numTabs;

	public DemoCustomJTabbedPane() {
		createGUI();
		setDisplay();
	}

	/** set diplay for JFrame */
	private void setDisplay() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(450, 300);
		setLocationRelativeTo(null);
		setVisible(true);
	}

	/** set title and add JTabbedPane into JFrame */
	private void createGUI() {
		setTitle("Demo custum JTabbedPane");
		createJTabbedPane();
		add(tabbedPane);
	}

	/** create JTabbedPane contain 2 tab */
	private void createJTabbedPane() {
		/* create JTabbedPane */
		tabbedPane = new JTabbedPane(JTabbedPane.TOP,
				JTabbedPane.SCROLL_TAB_LAYOUT);

		/* add first tab */
		tabbedPane.add(createJPanel(), "Tab " + String.valueOf(numTabs),
				numTabs++);
		tabbedPane.setTabComponentAt(0, new DemoCustomTab(this));

		/* add tab to add new tab when click */
		tabbedPane.add(new JPanel(), "+", numTabs++);

		tabbedPane.addChangeListener(changeListener);
	}

	/** create JPanel contain a JLabel */
	private JPanel createJPanel() {
		JPanel panel = new JPanel(new GridLayout(1, 1));
		panel.add(new JScrollPane(createTextArea(10, 40)));
		return panel;
	}

	private JTextArea createTextArea(int row, int col) {
		JTextArea ta = new JTextArea(row, col);
		ta.setWrapStyleWord(true);
		ta.setLineWrap(true);
		ta.setForeground(Color.BLUE);
		return ta;
	}

	ChangeListener changeListener = new ChangeListener() {
		@Override
		public void stateChanged(ChangeEvent e) {
			addNewTab();
		}
	};

	private void addNewTab() {
		int index = numTabs - 1;
		if (tabbedPane.getSelectedIndex() == index) { /* if click new tab */
			/* add new tab */
			tabbedPane.add(createJPanel(), "Tab " + String.valueOf(index),
					index);
			/* set tab is custom tab */
			tabbedPane.setTabComponentAt(index, new DemoCustomTab(this));
			tabbedPane.removeChangeListener(changeListener);
			tabbedPane.setSelectedIndex(index);
			tabbedPane.addChangeListener(changeListener);
			numTabs++;
		}
	}

	public void removeTab(int index) {
		tabbedPane.remove(index);
		numTabs--;

		if (index == numTabs - 1 && index > 0) {
			tabbedPane.setSelectedIndex(numTabs - 2);
		} else {
			tabbedPane.setSelectedIndex(index);
		}

		if (numTabs == 1) {
			addNewTab();
		}
	}

	public static void main(String[] args) {
		new DemoCustomJTabbedPane();
	}
}

Have you noticed in line 51 we add the first tab as usual, then in line 53 we perform setTabComponentAt to replace the default tab by tab that we customize (code below) close tab button.

Current 58 perform event listener transfer of JTabbedPane tab.

Method addNewTab perform additional new tab. Notice the line 91, after adding a new tab, then we need to interrupt the listening of JTabbedPane because otherwise the condition tabbedPane.getSelectedIndex() == index always right and it will take a lot more tab. After turning off the listen, we put the tab is selected as the newly created tab and then listen back mount.

Method removeTab shall pay the tab at position index. Note the if-else command first checks if the last closed tab will focus on the tab before it, if not will focus on the tab after it. First if statement 2 to check if close all tabs (only one button to add tab) are automatically generated 1 new tab.

Add to JTabbedPane tab close button


On the play button tab, we need to implement custom components (component) the tab is 1 JPanel, This JPanel containing 1 JLabel show title (title) tab and 1 JButton to capture close event like this tab

added close button on the tab JTabbedPane

Here is the code to customize Tab

package nguyenvanquan7826.JTabbedPane;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;

/**
 * --------------------- @author nguyenvanquan7826 ---------------------
 * ------------------ website: cachhoc.net -------------------
 * ---------- date: Jul 24, 2014 - filename: DemoButtonTab.java ----------
 */
public class DemoCustomTab extends JPanel {

	DemoCustomJTabbedPane customJTabbedPane;

	/** JPanel contain a JLabel and a JButton to close */
	public DemoCustomTab(DemoCustomJTabbedPane customJTabbedPane) {
		this.customJTabbedPane = customJTabbedPane;
		setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
		setBorder(new EmptyBorder(5, 2, 2, 2));
		setOpaque(false);
		addLabel();
		add(new CustomButton("x"));
	}

	private void addLabel() {
		JLabel label = new JLabel() {
			/** set text for JLabel, it will title of tab */
			public String getText() {
				int index = customJTabbedPane.tabbedPane
						.indexOfTabComponent(DemoCustomTab.this);
				if (index != -1) {
					return customJTabbedPane.tabbedPane.getTitleAt(index);
				}
				return null;
			}
		};
		/** add more space between the label and the button */
		label.setBorder(new EmptyBorder(0, 0, 0, 10));
		add(label);
	}

	class CustomButton extends JButton implements MouseListener {
		public CustomButton(String text) {
			int size = 15;
			setText(text);
			/** set size for button close */
			setPreferredSize(new Dimension(size, size));

			setToolTipText("close the Tab");

			/** set transparent */
			setContentAreaFilled(false);

			/** set border for button */
			setBorder(new EtchedBorder());
			/** don't show border */
			setBorderPainted(false);

			setFocusable(false);

			/** add event with mouse */
			addMouseListener(this);

		}

		/** when click button, tab will close */
		@Override
		public void mouseClicked(MouseEvent e) {
			int index = customJTabbedPane.tabbedPane
					.indexOfTabComponent(DemoCustomTab.this);
			if (index != -1) {
				customJTabbedPane.removeTab(index);
			}
		}

		@Override
		public void mousePressed(MouseEvent e) {
		}

		@Override
		public void mouseReleased(MouseEvent e) {
		}

		/** show border button when mouse hover */
		@Override
		public void mouseEntered(MouseEvent e) {
			setBorderPainted(true);
			setForeground(Color.RED);
		}

		/** hide border when mouse not hover */
		@Override
		public void mouseExited(MouseEvent e) {
			setBorderPainted(false);
			setForeground(Color.BLACK);
		}
	}
}

In this class we have 1 object DemoCustomJTabbedPane, object that is passed into which we created in the previous code that you noticed that we have called new DemoCustomTab(this). The goal is to transfer it to get JTabbedPane Ongoing, we'll work with it and also to perform more close tab. Specifically,:

Have you seen this class inherits JPanel so that it is 1 JPanel as we want. We do put JLabel and JButton into it at the line 30 and 31.

Method addLabel perform additional JLabel on JPanel. But we need to take the title of the tab to show up JLabel by overriding function getText JLabel and implementation of looking to the current tab of JTabbedPane to take title.

Adding simple JButton in creating 1 JButton with the text “x” however if you do so, it will be very loud and JButton bad, so its also customize it with class JButton CustomButton.
This Class implements MouseListener began to perform with mouse events. When you hover over the button, the method close mouseEntered will be executed and the color will change to red, contour is also up and 1 tool tip text displayed “close the tab”. When you hover out the back to normal by means of mouseExited.
To get things on the need to put some value to it as:
– Place the appropriate size: setPreferredSize(new Dimension(size, size));
– How transparent button: setContentAreaFilled(false);
– Put contour: setBorder(new EtchedBorder()); setBorderPainted(false);
When you click on the button to close the tab methods mouseClicked known and implemented method call removeTab of DemoCustomJTabbedPane to close the tab.

Read it in English here