I created a JStatusBar from a variety of nested JPanels . I was surprised how many JPanels it took to create the status bar.
JPanels JPanels everywhere.
Here's a test graphical interface.

And here is the JStatusBar class. The status bar has the leftmost status update area. On the right, you can add as many status areas as you want, with a dividing bar. The only limitation is the width of the status bar.
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import javax.swing.JComponent; import javax.swing.JPanel; public class JStatusBar extends JPanel { private static final long serialVersionUID = 1L; protected JPanel leftPanel; protected JPanel rightPanel; public JStatusBar() { createPartControl(); } protected void createPartControl() { setLayout(new BorderLayout()); setPreferredSize(new Dimension(getWidth(), 23)); leftPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 3)); leftPanel.setOpaque(false); add(leftPanel, BorderLayout.WEST); rightPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 5, 3)); rightPanel.setOpaque(false); add(rightPanel, BorderLayout.EAST); } public void setLeftComponent(JComponent component) { leftPanel.add(component); } public void addRightComponent(JComponent component) { JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 5, 0)); panel.add(new SeparatorPanel(Color.GRAY, Color.WHITE)); panel.add(component); rightPanel.add(panel); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); int y = 0; g.setColor(new Color(156, 154, 140)); g.drawLine(0, y, getWidth(), y); y++; g.setColor(new Color(196, 194, 183)); g.drawLine(0, y, getWidth(), y); y++; g.setColor(new Color(218, 215, 201)); g.drawLine(0, y, getWidth(), y); y++; g.setColor(new Color(233, 231, 217)); g.drawLine(0, y, getWidth(), y); y = getHeight() - 3; g.setColor(new Color(233, 232, 218)); g.drawLine(0, y, getWidth(), y); y++; g.setColor(new Color(233, 231, 216)); g.drawLine(0, y, getWidth(), y); y++; g.setColor(new Color(221, 221, 220)); g.drawLine(0, y, getWidth(), y); } }
The separator bar is another JPanel .
import java.awt.Color; import java.awt.Graphics; import javax.swing.JPanel; public class SeparatorPanel extends JPanel { private static final long serialVersionUID = 1L; protected Color leftColor; protected Color rightColor; public SeparatorPanel(Color leftColor, Color rightColor) { this.leftColor = leftColor; this.rightColor = rightColor; setOpaque(false); } @Override protected void paintComponent(Graphics g) { g.setColor(leftColor); g.drawLine(0, 0, 0, getHeight()); g.setColor(rightColor); g.drawLine(1, 0, 1, getHeight()); } }
And finally, a simulator class that shows you how to use JStatusBar .
import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingUtilities; public class StatusBarSimulator implements Runnable { protected TimerThread timerThread; @Override public void run() { JFrame frame = new JFrame(); frame.setBounds(100, 200, 400, 200); frame.setTitle("Status Bar Simulator"); Container contentPane = frame.getContentPane(); contentPane.setLayout(new BorderLayout()); JStatusBar statusBar = new JStatusBar(); JLabel leftLabel = new JLabel("Your application is running."); statusBar.setLeftComponent(leftLabel); final JLabel dateLabel = new JLabel(); dateLabel.setHorizontalAlignment(JLabel.CENTER); statusBar.addRightComponent(dateLabel); final JLabel timeLabel = new JLabel(); timeLabel.setHorizontalAlignment(JLabel.CENTER); statusBar.addRightComponent(timeLabel); contentPane.add(statusBar, BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent event) { exitProcedure(); } }); timerThread = new TimerThread(dateLabel, timeLabel); timerThread.start(); frame.setVisible(true); } public void exitProcedure() { timerThread.setRunning(false); System.exit(0); } public static void main(String[] args) { SwingUtilities.invokeLater(new StatusBarSimulator()); } public class TimerThread extends Thread { protected boolean isRunning; protected JLabel dateLabel; protected JLabel timeLabel; protected SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy"); protected SimpleDateFormat timeFormat = new SimpleDateFormat("h:mm a"); public TimerThread(JLabel dateLabel, JLabel timeLabel) { this.dateLabel = dateLabel; this.timeLabel = timeLabel; this.isRunning = true; } @Override public void run() { while (isRunning) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Calendar currentCalendar = Calendar.getInstance(); Date currentTime = currentCalendar.getTime(); dateLabel.setText(dateFormat.format(currentTime)); timeLabel.setText(timeFormat.format(currentTime)); } }); try { Thread.sleep(5000L); } catch (InterruptedException e) { } } } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } } }