Like the one we add into the corner of presentation slides.
I already have SwingX library added and working, in case that could help with something.
Like the one we add into the corner of presentation slides.
I already have SwingX library added and working, in case that could help with something.
Basically, you want to use a JLabel
for displaying the date/time, a javax.swing.Timer
set to a regular interval to update the label and a DateFormat
instance to format the date value...
public class PlaySchoolClock {
public static void main(String[] args) {
new PlaySchoolClock();
}
public PlaySchoolClock() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ClockPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ClockPane extends JPanel {
private JLabel clock;
public ClockPane() {
setLayout(new BorderLayout());
clock = new JLabel();
clock.setHorizontalAlignment(JLabel.CENTER);
clock.setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD, 48f));
tickTock();
add(clock);
Timer timer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tickTock();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.setInitialDelay(0);
timer.start();
}
public void tickTock() {
clock.setText(DateFormat.getDateTimeInstance().format(new Date()));
}
}
}
This example uses a time interval of half a second. The main reason for this is I don't go to the trouble of trying to calculate how far we are away from the next second when we set up the initial delay. This ensures that we are always up-to-date
The next question is to ask "why?" This kind of setup is relatively expensive, with the timer firing every half second (to catch any edge cases) and updating the screen, when most OS's actually have a date/time already on the screen...IMHO
I created a JStatusBar
from many nested JPanels
. I was surprised at how many JPanels
it took to create a status bar.
JPanels
. JPanels
everywhere.
Here's the test GUI.
And here's the JStatusBar class. The status bar has a leftmost status update area. On the right, you can add as many status areas as you want, with a separator bar. The only limit 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 yet 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, the simulator class that shows you how to use the 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;
}
}
}
Add a label component at the appropriate place in your JFrame's component hirerarchy (maybe a JToolBar?).
Then create a timer that fires once per second, and add an ActionListener to it that updates the text of the label with the current time.
See the accepted answer at Using SwingWorker and Timer to display time on a label?
Create a SimpleDateFormat
object that will help you format the current date. Add a JLabel
to your JFrame
. In a separate thread, create a loop that keeps reading the current date, format it to a String
and pass it to the JLabel
in the EDT. Make the separate thread sleep for one second or less before updating the label again.