Stoplight Simulator allows a user to control a simulated stoplight by clicking the "Change" button or by selecting the "Change" item from the Edit menu.
File menu options are:
· Save: saves the current stoplight in it's current state to a file.
· Open: replaces the current stoplight by one read from a file.
· New: replaces the current stoplight by a new one.
· Quit: terminates the application.
When the user attempts to replace the existing stoplight or attempts to terminate the application a warning dialog box appears:
A file chooser dialog appears when the user saves or opens a file:
The Help menu options are "Help" and "About". Selecting "About" displays copyright and contact information:
Selecting "Help" displays information on how to use the application:
Stoplight Simulator instantiates the Model-View-Controller architecture. The Stoplight class plays the model role, the StoplightView class plays the role of view, and the AppPanel class plays the role of controller:
In the earlier screen shots the pink sub-panel corresponds to an instance of the ControlPanel class, the gray sub-panel corresponds to an instance of the StoplightView class, and the stoplight image corresponds to an instance of the StoplightShape class. \
The main attribute of a Stoplight instance is it's color—red, green, yellow. The change() method toggles the color from red to green to yellow and back to red.
We use the Publisher-Subscriber pattern to alert the view when the color of the stoplight has changed:
The panels all inherit from Java's JPanel class:
In addition, the AppPanel implements Java's ActionListener interface. This is another example of the Publisher-Subscriber pattern. In this case the menu items and the "Change" button are publishers. They fire action events when selected or clicked. The AppPanel subscribes to these publishers and will perform the required actions when notified.
Here's a sequence diagram showing what happens when the "Change" button is clicked:
For convenience, all of the code is in a single Stoplight.java file. In practice this would be divided into one file for each class.
This is a classic MVC architecture:
The controller listens for user input, then makes some change to the model. The model notifies subscribers. The view is notified, fetches the changes from the model, then re-draws itself. Note that there are no associations from the model to either the controller and the view. This means we can change the user interface or provide multiple user interfaces to different classes of users (e.g., admins, customers, sales, etc.) without changing the business logic (i.e., the model).
Everything we see in a desktop window is a graphics component (JComponent). There are two major types: panels and controls. Controls include buttons, drop-down lists, sliders, etc. A panel is a component that contains other components, including (sub-) panels. This is just the Composite Design Pattern:
We can make our own components. This is what we did with StopLightView. It extends JPanel (hence JComponent) and has a paintComponent method which takes a graphical context as input. We can regard the graphical context as a coordinate system (called user space) that the JVM will map onto some portion of the screen (called device space).
The graphical context is passed to the draw method of the StopLightShape class. This is where the artwork happens. It's convenient to have this as a separate class in case many stoplights are needed.
See Java Graphics Programming for more details.