使用 GUI 在 BlueJ 中显示时钟
Clock Display in BlueJ with GUI
目前显示正常。我将分钟 运行 编码为模拟时钟显示的秒。它工作正常,但是当它是 12:59 时,它应该是 1 而不是 0。我无法弄清楚要删除 00:00 应该是 12:59 之后的 01:00。
clock.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Clock
{
private JFrame frame;
private JLabel label;
private ClockDisplay clock;
private boolean clockRunning = false;
private TimerThread timerThread;
/**
* Constructor for objects of class Clock
*/
public Clock()
{
makeFrame();
clock = new ClockDisplay();
}
/**
*
*/
private void start()
{
clockRunning = true;
timerThread = new TimerThread();
timerThread.start();
}
/**
*
*/
private void stop()
{
clockRunning = false;
}
/**
*
*/
private void step()
{
clock.timeTick();
label.setText(clock.getTime());
}
/**
* 'About' function: show the 'about' box.
*/
private void showAbout()
{
JOptionPane.showMessageDialog (frame,
"Clock Version 1.0\n" +
"A simple interface for the 'Objects First' clock display project",
"About Clock",
JOptionPane.INFORMATION_MESSAGE);
}
/**
* Quit function: quit the application.
*/
private void quit()
{
System.exit(0);
}
/**
* Create the Swing frame and its content.
*/
private void makeFrame()
{
frame = new JFrame("Clock");
JPanel contentPane = (JPanel)frame.getContentPane();
contentPane.setBorder(new EmptyBorder(1, 60, 1, 60));
makeMenuBar(frame);
// Specify the layout manager with nice spacing
contentPane.setLayout(new BorderLayout(12, 12));
// Create the image pane in the center
label = new JLabel("00:00", SwingConstants.CENTER);
Font displayFont = label.getFont().deriveFont(96.0f);
label.setFont(displayFont);
//imagePanel.setBorder(new EtchedBorder());
contentPane.add(label, BorderLayout.CENTER);
// Create the toolbar with the buttons
JPanel toolbar = new JPanel();
toolbar.setLayout(new GridLayout(1, 0));
JButton startButton = new JButton("Start");
startButton.addActionListener(e -> start());
toolbar.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(e -> stop());
toolbar.add(stopButton);
JButton stepButton = new JButton("Step");
stepButton.addActionListener(e -> step());
toolbar.add(stepButton);
// Add toolbar into panel with flow layout for spacing
JPanel flow = new JPanel();
flow.add(toolbar);
contentPane.add(flow, BorderLayout.SOUTH);
// building is done - arrange the components
frame.pack();
// place the frame at the center of the screen and show
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2);
frame.setVisible(true);
}
/**
* Create the main frame's menu bar.
*
* @param frame The frame that the menu bar should be added to.
*/
private void makeMenuBar(JFrame frame)
{
final int SHORTCUT_MASK =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
JMenuBar menubar = new JMenuBar();
frame.setJMenuBar(menubar);
JMenu menu;
JMenuItem item;
// create the File menu
menu = new JMenu("File");
menubar.add(menu);
item = new JMenuItem("About Clock...");
item.addActionListener(e -> showAbout());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Quit");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK));
item.addActionListener(e -> quit());
menu.add(item);
}
class TimerThread extends Thread
{
public void run()
{
while (clockRunning) {
step();
pause();
}
}
private void pause()
{
try {
Thread.sleep(300); // pause for 300 milliseconds
}
catch (InterruptedException exc) {
}
}
}
}
clock.java 应该被锁定,因为它工作正常。
numDisplay.java
/**
* The NumberDisplay class represents a digital number display that can hold
* values from zero to a given limit. The limit can be specified when
* creating the display. The values range from zero (inclusive) to limit-1.
* If used,
* for example, for the seconds on a digital clock, the limit would be 60,
* resulting in display values from 0 to 59. When incremented, the display
* automatically rolls over to zero when reaching the limit.
*/
public class NumberDisplay
{
private int limit = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay.
* Set the limit at which the display rolls over.
*/
public NumberDisplay(int rollOverLimit)
{
limit = rollOverLimit;
value = 1;
}
/*
*
*/
/**
* Return the current value.
*/
public int getValue()
{
return value;
}
/**
* Return the display value (that is, the current value as a two-digit
* String. If the value is less than ten, it will be padded with a leading
* zero).
*/
public String getDisplayValue()
{
if(value < 10) {
return "0" + value; // stay 0 appears in left
}
else {
return "" + value; // none to show in right of the display
}
}
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public void setValue(int replacementValue)
{
if((replacementValue >= 2) & (replacementValue < limit)) {
value = replacementValue;
}
}
/**
* Increment the display value by one, rolling over to zero if the
* limit is reached.
*/
public void increment()
{
value = (value + 1) % limit; // this is already the time by 1
}
}
我还留下了评论以帮助理解它们是什么 运行ning 程序。
这是最后一个名为 "Display" 的 ClockDisplay.java:
/**
* The ClockDisplay class implements a digital clock display for a
* European-style 24 hour clock. The clock shows hours and minutes. The
* range of the clock is 00:00 (midnight) to 23:59 (one minute before
* midnight).
*
* The clock display receives "ticks" (via the timeTick method) every minute
* and reacts by incrementing the display. This is done in the usual clock
* fashion: the hour increments when the minutes roll over to zero.
*/
public class ClockDisplay
{
private NumberDisplay hours; // runs from 1 am/pm to 11:59 am/pm
private NumberDisplay minutes; // This will running like
// seconds act as minutes.
private String displayString; // simulates the actual display
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at 00:00.
*/
public ClockDisplay()
{
hours = new NumberDisplay(13); // set great than 13; runs from 1am to 12 noon
minutes = new NumberDisplay(60); // 60 minutes is one hour
updateDisplay();
}
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at the time specified by the
* parameters.
*/
public ClockDisplay(int hour, int minute)
{
hours = new NumberDisplay(13);
minutes = new NumberDisplay(60);
setTime(hour, minute);
}
/**
* This method should get called once every minute - it makes
* the clock display go one minute forward.
*/
public void timeTick()
{
minutes.increment();
if(minutes.getValue() == 1) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
/**
* Set the time of the display to the specified hour and
* minute.
*/
public void setTime(int hour, int minute)
{
hours.setValue(hour); // hours will be set on display
minutes.setValue(minute); // minutes will be set on display
updateDisplay(); // updating the value to display
}
/**
* Return the current time of this display in the format HH:MM.
*/
public String getTime()
{
return displayString; // appears as messagebox to display the clock
}
/**
* Update the internal string that represents the display.
*/
private void updateDisplay()
{
displayString = hours.getDisplayValue() + ":" +
minutes.getDisplayValue(); //Updated the clock simulator
}
}
我仍然坚持 00:00。需要帮助吗?
您的代码中有很多地方可以更好地管理。
让我们从……开始吧
public void increment() {
value = (value + 1) % limit; // this is already the time by 1
}
我明白你想做什么,但请记住 13 % 13
是 0
,这是你问题的起点,虽然肯定很聪明,但我会使用 [=16] =] 并允许 setValue
执行验证。
这样做的原因是,您可以提供最小和最大允许值,然后 setValue
可以管理这些值。
然后我会将 increment
方法更改为 return true
当它 "rolls" 值时,这样会更容易确定值何时恢复到最低状态。
为简洁起见,这些是基本更改...
NumberDisplay
public class NumberDisplay {
private int minimum = 1;
private int maximum = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay. Set the limit at
* which the display rolls over.
*/
public NumberDisplay(int maxumum, int minimum) {
this.maximum = maxumum;
this.minimum = minimum;
value = 1;
}
//...
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public boolean setValue(int replacementValue) {
if (replacementValue >= maximum) {
value = minimum;
return true;
} else {
value = replacementValue;
return false;
}
}
/**
* Increment the display value by one, rolling over to zero if the limit
* is reached.
*/
public boolean increment() {
// 值 = (值 + 1) % 最大值; // 这已经是 1 的时间了
return 设置值(值 + 1);
}
}
ClockDisplay
public class ClockDisplay {
//...
/**
* This method should get called once every minute - it makes the clock
* display go one minute forward.
*/
public void timeTick() {
if (minutes.increment()) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
//...
}
完整示例....
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Clock {
private JFrame frame;
private JLabel label;
private ClockDisplay clock;
private boolean clockRunning = false;
private TimerThread timerThread;
public static void main(String[] args) {
System.out.println((13 % 13));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Clock();
}
});
}
/**
* Constructor for objects of class Clock
*/
public Clock() {
makeFrame();
clock = new ClockDisplay(12, 0);
}
/**
*
*/
private void start() {
clockRunning = true;
timerThread = new TimerThread();
timerThread.start();
}
/**
*
*/
private void stop() {
clockRunning = false;
}
/**
*
*/
private void step() {
clock.timeTick();
label.setText(clock.getTime());
}
/**
* 'About' function: show the 'about' box.
*/
private void showAbout() {
JOptionPane.showMessageDialog(frame,
"Clock Version 1.0\n"
+ "A simple interface for the 'Objects First' clock display project",
"About Clock",
JOptionPane.INFORMATION_MESSAGE);
}
/**
* Quit function: quit the application.
*/
private void quit() {
System.exit(0);
}
/**
* Create the Swing frame and its content.
*/
private void makeFrame() {
frame = new JFrame("Clock");
JPanel contentPane = (JPanel) frame.getContentPane();
contentPane.setBorder(new EmptyBorder(1, 60, 1, 60));
makeMenuBar(frame);
// Specify the layout manager with nice spacing
contentPane.setLayout(new BorderLayout(12, 12));
// Create the image pane in the center
label = new JLabel("12:00", SwingConstants.CENTER);
Font displayFont = label.getFont().deriveFont(96.0f);
label.setFont(displayFont);
//imagePanel.setBorder(new EtchedBorder());
contentPane.add(label, BorderLayout.CENTER);
// Create the toolbar with the buttons
JPanel toolbar = new JPanel();
toolbar.setLayout(new GridLayout(1, 0));
JButton startButton = new JButton("Start");
startButton.addActionListener(e -> start());
toolbar.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(e -> stop());
toolbar.add(stopButton);
JButton stepButton = new JButton("Step");
stepButton.addActionListener(e -> step());
toolbar.add(stepButton);
// Add toolbar into panel with flow layout for spacing
JPanel flow = new JPanel();
flow.add(toolbar);
contentPane.add(flow, BorderLayout.SOUTH);
// building is done - arrange the components
frame.pack();
// place the frame at the center of the screen and show
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width / 2 - frame.getWidth() / 2, d.height / 2 - frame.getHeight() / 2);
frame.setVisible(true);
}
/**
* Create the main frame's menu bar.
*
* @param frame The frame that the menu bar should be added to.
*/
private void makeMenuBar(JFrame frame) {
final int SHORTCUT_MASK
= Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
JMenuBar menubar = new JMenuBar();
frame.setJMenuBar(menubar);
JMenu menu;
JMenuItem item;
// create the File menu
menu = new JMenu("File");
menubar.add(menu);
item = new JMenuItem("About Clock...");
item.addActionListener(e -> showAbout());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Quit");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK));
item.addActionListener(e -> quit());
menu.add(item);
}
class TimerThread extends Thread {
public void run() {
while (clockRunning) {
step();
pause();
}
}
private void pause() {
try {
Thread.sleep(300); // pause for 300 milliseconds
} catch (InterruptedException exc) {
}
}
}
public class NumberDisplay {
private int minimum = 1;
private int maximum = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay. Set the limit at
* which the display rolls over.
*/
public NumberDisplay(int maxumum, int minimum) {
this.maximum = maxumum;
this.minimum = minimum;
value = 1;
}
/*
*
*/
/**
* Return the current value.
*/
public int getValue() {
return value;
}
/**
* Return the display value (that is, the current value as a two-digit
* String. If the value is less than ten, it will be padded with a
* leading zero).
*/
public String getDisplayValue() {
if (value < 10) {
return "0" + value; // stay 0 appears in left
} else {
return "" + value; // none to show in right of the display
}
}
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public boolean setValue(int replacementValue) {
if (replacementValue >= maximum) {
value = minimum;
return true;
} else {
value = replacementValue;
return false;
}
}
/**
* Increment the display value by one, rolling over to zero if the limit
* is reached.
*/
public boolean increment() {
// value = (value + 1) % maximum; // this is already the time by 1
return setValue(value + 1);
}
}
public class ClockDisplay {
private NumberDisplay hours; // runs from 1 am/pm to 11:59 am/pm
private NumberDisplay minutes; // This will running like
// seconds act as minutes.
private String displayString; // simulates the actual display
/**
* Constructor for ClockDisplay objects. This constructor creates a new
* clock set at 00:00.
*/
public ClockDisplay() {
hours = new NumberDisplay(13, 1); // set great than 13; runs from 1am to 12 noon
minutes = new NumberDisplay(60, 0); // 60 minutes is one hour
updateDisplay();
}
/**
* Constructor for ClockDisplay objects. This constructor creates a new
* clock set at the time specified by the parameters.
*/
public ClockDisplay(int hour, int minute) {
this();
setTime(hour, minute);
}
/**
* This method should get called once every minute - it makes the clock
* display go one minute forward.
*/
public void timeTick() {
if (minutes.increment()) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
/**
* Set the time of the display to the specified hour and minute.
*/
public void setTime(int hour, int minute) {
System.out.println("setTime " + hour + ":" + minute);
hours.setValue(hour); // hours will be set on display
minutes.setValue(minute); // minutes will be set on display
updateDisplay(); // updating the value to display
}
/**
* Return the current time of this display in the format HH:MM.
*/
public String getTime() {
return displayString; // appears as messagebox to display the clock
}
/**
* Update the internal string that represents the display.
*/
private void updateDisplay() {
displayString = hours.getDisplayValue() + ":"
+ minutes.getDisplayValue(); //Updated the clock simulator
}
}
}
旁注
您还需要更好地了解 Swing 中的并发性。 Swing 不是线程安全的,你永远不应该修改 UI 或 UI 所依赖的东西,从事件调度线程的上下文之外,请参阅 Concurrency in Swing for more details. A Swing Timer
将是一个更好的选择在这种情况下线程
目前显示正常。我将分钟 运行 编码为模拟时钟显示的秒。它工作正常,但是当它是 12:59 时,它应该是 1 而不是 0。我无法弄清楚要删除 00:00 应该是 12:59 之后的 01:00。
clock.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Clock
{
private JFrame frame;
private JLabel label;
private ClockDisplay clock;
private boolean clockRunning = false;
private TimerThread timerThread;
/**
* Constructor for objects of class Clock
*/
public Clock()
{
makeFrame();
clock = new ClockDisplay();
}
/**
*
*/
private void start()
{
clockRunning = true;
timerThread = new TimerThread();
timerThread.start();
}
/**
*
*/
private void stop()
{
clockRunning = false;
}
/**
*
*/
private void step()
{
clock.timeTick();
label.setText(clock.getTime());
}
/**
* 'About' function: show the 'about' box.
*/
private void showAbout()
{
JOptionPane.showMessageDialog (frame,
"Clock Version 1.0\n" +
"A simple interface for the 'Objects First' clock display project",
"About Clock",
JOptionPane.INFORMATION_MESSAGE);
}
/**
* Quit function: quit the application.
*/
private void quit()
{
System.exit(0);
}
/**
* Create the Swing frame and its content.
*/
private void makeFrame()
{
frame = new JFrame("Clock");
JPanel contentPane = (JPanel)frame.getContentPane();
contentPane.setBorder(new EmptyBorder(1, 60, 1, 60));
makeMenuBar(frame);
// Specify the layout manager with nice spacing
contentPane.setLayout(new BorderLayout(12, 12));
// Create the image pane in the center
label = new JLabel("00:00", SwingConstants.CENTER);
Font displayFont = label.getFont().deriveFont(96.0f);
label.setFont(displayFont);
//imagePanel.setBorder(new EtchedBorder());
contentPane.add(label, BorderLayout.CENTER);
// Create the toolbar with the buttons
JPanel toolbar = new JPanel();
toolbar.setLayout(new GridLayout(1, 0));
JButton startButton = new JButton("Start");
startButton.addActionListener(e -> start());
toolbar.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(e -> stop());
toolbar.add(stopButton);
JButton stepButton = new JButton("Step");
stepButton.addActionListener(e -> step());
toolbar.add(stepButton);
// Add toolbar into panel with flow layout for spacing
JPanel flow = new JPanel();
flow.add(toolbar);
contentPane.add(flow, BorderLayout.SOUTH);
// building is done - arrange the components
frame.pack();
// place the frame at the center of the screen and show
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width/2 - frame.getWidth()/2, d.height/2 - frame.getHeight()/2);
frame.setVisible(true);
}
/**
* Create the main frame's menu bar.
*
* @param frame The frame that the menu bar should be added to.
*/
private void makeMenuBar(JFrame frame)
{
final int SHORTCUT_MASK =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
JMenuBar menubar = new JMenuBar();
frame.setJMenuBar(menubar);
JMenu menu;
JMenuItem item;
// create the File menu
menu = new JMenu("File");
menubar.add(menu);
item = new JMenuItem("About Clock...");
item.addActionListener(e -> showAbout());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Quit");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK));
item.addActionListener(e -> quit());
menu.add(item);
}
class TimerThread extends Thread
{
public void run()
{
while (clockRunning) {
step();
pause();
}
}
private void pause()
{
try {
Thread.sleep(300); // pause for 300 milliseconds
}
catch (InterruptedException exc) {
}
}
}
}
clock.java 应该被锁定,因为它工作正常。
numDisplay.java
/**
* The NumberDisplay class represents a digital number display that can hold
* values from zero to a given limit. The limit can be specified when
* creating the display. The values range from zero (inclusive) to limit-1.
* If used,
* for example, for the seconds on a digital clock, the limit would be 60,
* resulting in display values from 0 to 59. When incremented, the display
* automatically rolls over to zero when reaching the limit.
*/
public class NumberDisplay
{
private int limit = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay.
* Set the limit at which the display rolls over.
*/
public NumberDisplay(int rollOverLimit)
{
limit = rollOverLimit;
value = 1;
}
/*
*
*/
/**
* Return the current value.
*/
public int getValue()
{
return value;
}
/**
* Return the display value (that is, the current value as a two-digit
* String. If the value is less than ten, it will be padded with a leading
* zero).
*/
public String getDisplayValue()
{
if(value < 10) {
return "0" + value; // stay 0 appears in left
}
else {
return "" + value; // none to show in right of the display
}
}
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public void setValue(int replacementValue)
{
if((replacementValue >= 2) & (replacementValue < limit)) {
value = replacementValue;
}
}
/**
* Increment the display value by one, rolling over to zero if the
* limit is reached.
*/
public void increment()
{
value = (value + 1) % limit; // this is already the time by 1
}
}
我还留下了评论以帮助理解它们是什么 运行ning 程序。
这是最后一个名为 "Display" 的 ClockDisplay.java:
/**
* The ClockDisplay class implements a digital clock display for a
* European-style 24 hour clock. The clock shows hours and minutes. The
* range of the clock is 00:00 (midnight) to 23:59 (one minute before
* midnight).
*
* The clock display receives "ticks" (via the timeTick method) every minute
* and reacts by incrementing the display. This is done in the usual clock
* fashion: the hour increments when the minutes roll over to zero.
*/
public class ClockDisplay
{
private NumberDisplay hours; // runs from 1 am/pm to 11:59 am/pm
private NumberDisplay minutes; // This will running like
// seconds act as minutes.
private String displayString; // simulates the actual display
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at 00:00.
*/
public ClockDisplay()
{
hours = new NumberDisplay(13); // set great than 13; runs from 1am to 12 noon
minutes = new NumberDisplay(60); // 60 minutes is one hour
updateDisplay();
}
/**
* Constructor for ClockDisplay objects. This constructor
* creates a new clock set at the time specified by the
* parameters.
*/
public ClockDisplay(int hour, int minute)
{
hours = new NumberDisplay(13);
minutes = new NumberDisplay(60);
setTime(hour, minute);
}
/**
* This method should get called once every minute - it makes
* the clock display go one minute forward.
*/
public void timeTick()
{
minutes.increment();
if(minutes.getValue() == 1) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
/**
* Set the time of the display to the specified hour and
* minute.
*/
public void setTime(int hour, int minute)
{
hours.setValue(hour); // hours will be set on display
minutes.setValue(minute); // minutes will be set on display
updateDisplay(); // updating the value to display
}
/**
* Return the current time of this display in the format HH:MM.
*/
public String getTime()
{
return displayString; // appears as messagebox to display the clock
}
/**
* Update the internal string that represents the display.
*/
private void updateDisplay()
{
displayString = hours.getDisplayValue() + ":" +
minutes.getDisplayValue(); //Updated the clock simulator
}
}
我仍然坚持 00:00。需要帮助吗?
您的代码中有很多地方可以更好地管理。
让我们从……开始吧
public void increment() {
value = (value + 1) % limit; // this is already the time by 1
}
我明白你想做什么,但请记住 13 % 13
是 0
,这是你问题的起点,虽然肯定很聪明,但我会使用 [=16] =] 并允许 setValue
执行验证。
这样做的原因是,您可以提供最小和最大允许值,然后 setValue
可以管理这些值。
然后我会将 increment
方法更改为 return true
当它 "rolls" 值时,这样会更容易确定值何时恢复到最低状态。
为简洁起见,这些是基本更改...
NumberDisplay
public class NumberDisplay {
private int minimum = 1;
private int maximum = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay. Set the limit at
* which the display rolls over.
*/
public NumberDisplay(int maxumum, int minimum) {
this.maximum = maxumum;
this.minimum = minimum;
value = 1;
}
//...
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public boolean setValue(int replacementValue) {
if (replacementValue >= maximum) {
value = minimum;
return true;
} else {
value = replacementValue;
return false;
}
}
/**
* Increment the display value by one, rolling over to zero if the limit
* is reached.
*/
public boolean increment() {
// 值 = (值 + 1) % 最大值; // 这已经是 1 的时间了 return 设置值(值 + 1); } }
ClockDisplay
public class ClockDisplay {
//...
/**
* This method should get called once every minute - it makes the clock
* display go one minute forward.
*/
public void timeTick() {
if (minutes.increment()) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
//...
}
完整示例....
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Clock {
private JFrame frame;
private JLabel label;
private ClockDisplay clock;
private boolean clockRunning = false;
private TimerThread timerThread;
public static void main(String[] args) {
System.out.println((13 % 13));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Clock();
}
});
}
/**
* Constructor for objects of class Clock
*/
public Clock() {
makeFrame();
clock = new ClockDisplay(12, 0);
}
/**
*
*/
private void start() {
clockRunning = true;
timerThread = new TimerThread();
timerThread.start();
}
/**
*
*/
private void stop() {
clockRunning = false;
}
/**
*
*/
private void step() {
clock.timeTick();
label.setText(clock.getTime());
}
/**
* 'About' function: show the 'about' box.
*/
private void showAbout() {
JOptionPane.showMessageDialog(frame,
"Clock Version 1.0\n"
+ "A simple interface for the 'Objects First' clock display project",
"About Clock",
JOptionPane.INFORMATION_MESSAGE);
}
/**
* Quit function: quit the application.
*/
private void quit() {
System.exit(0);
}
/**
* Create the Swing frame and its content.
*/
private void makeFrame() {
frame = new JFrame("Clock");
JPanel contentPane = (JPanel) frame.getContentPane();
contentPane.setBorder(new EmptyBorder(1, 60, 1, 60));
makeMenuBar(frame);
// Specify the layout manager with nice spacing
contentPane.setLayout(new BorderLayout(12, 12));
// Create the image pane in the center
label = new JLabel("12:00", SwingConstants.CENTER);
Font displayFont = label.getFont().deriveFont(96.0f);
label.setFont(displayFont);
//imagePanel.setBorder(new EtchedBorder());
contentPane.add(label, BorderLayout.CENTER);
// Create the toolbar with the buttons
JPanel toolbar = new JPanel();
toolbar.setLayout(new GridLayout(1, 0));
JButton startButton = new JButton("Start");
startButton.addActionListener(e -> start());
toolbar.add(startButton);
JButton stopButton = new JButton("Stop");
stopButton.addActionListener(e -> stop());
toolbar.add(stopButton);
JButton stepButton = new JButton("Step");
stepButton.addActionListener(e -> step());
toolbar.add(stepButton);
// Add toolbar into panel with flow layout for spacing
JPanel flow = new JPanel();
flow.add(toolbar);
contentPane.add(flow, BorderLayout.SOUTH);
// building is done - arrange the components
frame.pack();
// place the frame at the center of the screen and show
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation(d.width / 2 - frame.getWidth() / 2, d.height / 2 - frame.getHeight() / 2);
frame.setVisible(true);
}
/**
* Create the main frame's menu bar.
*
* @param frame The frame that the menu bar should be added to.
*/
private void makeMenuBar(JFrame frame) {
final int SHORTCUT_MASK
= Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
JMenuBar menubar = new JMenuBar();
frame.setJMenuBar(menubar);
JMenu menu;
JMenuItem item;
// create the File menu
menu = new JMenu("File");
menubar.add(menu);
item = new JMenuItem("About Clock...");
item.addActionListener(e -> showAbout());
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Quit");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, SHORTCUT_MASK));
item.addActionListener(e -> quit());
menu.add(item);
}
class TimerThread extends Thread {
public void run() {
while (clockRunning) {
step();
pause();
}
}
private void pause() {
try {
Thread.sleep(300); // pause for 300 milliseconds
} catch (InterruptedException exc) {
}
}
}
public class NumberDisplay {
private int minimum = 1;
private int maximum = 13;
private int value;
/**
* Constructor for objects of class NumberDisplay. Set the limit at
* which the display rolls over.
*/
public NumberDisplay(int maxumum, int minimum) {
this.maximum = maxumum;
this.minimum = minimum;
value = 1;
}
/*
*
*/
/**
* Return the current value.
*/
public int getValue() {
return value;
}
/**
* Return the display value (that is, the current value as a two-digit
* String. If the value is less than ten, it will be padded with a
* leading zero).
*/
public String getDisplayValue() {
if (value < 10) {
return "0" + value; // stay 0 appears in left
} else {
return "" + value; // none to show in right of the display
}
}
/**
* Set the value of the display to the new specified value. If the new
* value is less than zero or over the limit, do nothing.
*/
public boolean setValue(int replacementValue) {
if (replacementValue >= maximum) {
value = minimum;
return true;
} else {
value = replacementValue;
return false;
}
}
/**
* Increment the display value by one, rolling over to zero if the limit
* is reached.
*/
public boolean increment() {
// value = (value + 1) % maximum; // this is already the time by 1
return setValue(value + 1);
}
}
public class ClockDisplay {
private NumberDisplay hours; // runs from 1 am/pm to 11:59 am/pm
private NumberDisplay minutes; // This will running like
// seconds act as minutes.
private String displayString; // simulates the actual display
/**
* Constructor for ClockDisplay objects. This constructor creates a new
* clock set at 00:00.
*/
public ClockDisplay() {
hours = new NumberDisplay(13, 1); // set great than 13; runs from 1am to 12 noon
minutes = new NumberDisplay(60, 0); // 60 minutes is one hour
updateDisplay();
}
/**
* Constructor for ClockDisplay objects. This constructor creates a new
* clock set at the time specified by the parameters.
*/
public ClockDisplay(int hour, int minute) {
this();
setTime(hour, minute);
}
/**
* This method should get called once every minute - it makes the clock
* display go one minute forward.
*/
public void timeTick() {
if (minutes.increment()) { // on clock at after 12 am or pm.
hours.increment(); // after 60 mins, next per hour.
}
updateDisplay(); // updating to return
}
/**
* Set the time of the display to the specified hour and minute.
*/
public void setTime(int hour, int minute) {
System.out.println("setTime " + hour + ":" + minute);
hours.setValue(hour); // hours will be set on display
minutes.setValue(minute); // minutes will be set on display
updateDisplay(); // updating the value to display
}
/**
* Return the current time of this display in the format HH:MM.
*/
public String getTime() {
return displayString; // appears as messagebox to display the clock
}
/**
* Update the internal string that represents the display.
*/
private void updateDisplay() {
displayString = hours.getDisplayValue() + ":"
+ minutes.getDisplayValue(); //Updated the clock simulator
}
}
}
旁注
您还需要更好地了解 Swing 中的并发性。 Swing 不是线程安全的,你永远不应该修改 UI 或 UI 所依赖的东西,从事件调度线程的上下文之外,请参阅 Concurrency in Swing for more details. A Swing Timer
将是一个更好的选择在这种情况下线程