May 28

In an earlier question we showed how to make a single tab flash. Since then many people have asked if it is possible to have more than one tab flashing.

To support multiple flashing tabs we need to refactor the original code a little to allow for a separate Timer for each tab that is flashing. This can achieved by moving the timer and flashing colour details into the listener as shown in the following code.

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;
import javax.swing.WindowConstants;

public class FlashingTab extends JTabbedPane {

	public Flasher flash(String tabName, Color fg, Color bg) {
		Flasher flasher = new Flasher(tabName, fg, bg);
		flasher.startFlashing();
		return flasher;
	}

	public static void main(String[] args) {
		JFrame frame = new JFrame();

		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		frame.setSize(300, 300);

		FlashingTab tabs = new FlashingTab();

		tabs.addTab("tab1", new JLabel("Tab 1"));
		tabs.addTab("tab2", new JLabel("Tab 2"));
		tabs.addTab("tab3", new JLabel("Tab 3"));
		tabs.addTab("tab4", new JLabel("Tab 4"));
		tabs.addTab("tab5", new JLabel("Tab 5"));

		tabs.flash("tab2", Color.green, Color.white);
		tabs.flash("tab5", Color.red, Color.yellow);
		frame.add(tabs);

		frame.setVisible(true);

	}

	public class Flasher implements ActionListener {

		private Color background;
		private Color foreground;
		private Color savedBackground;
		private Color savedForeground;
		private boolean on = false;
		private String tabName;
		private Timer timer = new Timer(1000, this);

		public Flasher(String tabName, Color fg, Color bg) {
			this.tabName = tabName;
			this.savedBackground = getBackground();
			this.savedForeground = getForeground();
			this.background = bg;
			this.foreground = fg;
		}

		public void startFlashing() {
			timer.start();
		}

		public void actionPerformed(ActionEvent e) {
			flash(on);
			on = !on;
		}

		public void flash(boolean on) {
			int tabIndex = indexOfTab(tabName);
			if (on) {

				if (foreground != null) {
					setForegroundAt(tabIndex, foreground);
				}
				if (background != null) {
					setBackgroundAt(tabIndex, background);
				}
			} else {
				if (savedForeground != null) {
					setForegroundAt(tabIndex, savedForeground);
				}
				if (savedBackground != null) {
					setBackgroundAt(tabIndex, savedBackground);
				}
			}
			repaint();
		}

		public void clearFlashing() {
			int tabIndex = indexOfTab(tabName);
			timer.stop();
			setForegroundAt(tabIndex, savedForeground);
			setBackgroundAt(tabIndex, savedBackground);
		}
	}
}

We chose to subclass JTabbedPane in the example for simplicity sakes, it’s not really required. With a few minor changes the listener would be able to be used with any JTabbedPane.

written by objects \\ tags: , ,


Leave a Reply

You must be logged in to post a comment.