TD4 — Swing: Car Control Panel
S7 Inf A3 — Java for Graphical and Mobile Programming
Stéphane Derrode — Centrale Lyon
Part 2 — GUI with Swing
Duration: 2h · Continue the td1 Maven project (or create td4)
Objectives
- Build a complete Swing window with
JFrameand nestedJPanels - Use
BorderLayout,FlowLayout, andGridLayout - Connect
ActionListenerevents to theCarmodel from Part 1 - Read and write component values (
JTextField,JLabel,JComboBox) - Use
JMenuBarandJOptionPane
Part 1 — Project Setup (5 min)
Reuse your td1 project which already contains Car.java.
Verify the three imports compile correctly in a new file:
If you need a fresh Maven project, create td4 with the same pom.xml as TD1 and copy Car.java into it.
Part 2 — CarUI — Basic Window (35 min)
2.1 Specification
Create src/main/java/com/s7infa3/CarUI.java.
The window must look like this:
┌─────────────────────────────────────┐
│ Car Control │ ← JFrame title
├─────────────────────────────────────┤
│ Car[Clio, 90hp, off, 0 km/h] │ ← NORTH: status JLabel
├─────────────────────────────────────┤
│ Model: [ Clio ] Power: [ 90 ] │ ← CENTER: JPanel (GridLayout)
│ Accel: [ 50 ] Turbo: [ ] │
├─────────────────────────────────────┤
│ [Start][Stop][Accelerate][Brake] │ ← SOUTH: JPanel (FlowLayout)
│ [New Car] │
└─────────────────────────────────────┘
2.2 Component inventory
| Component | Variable name | Initial state |
|---|---|---|
JLabel status display |
statusLabel |
car.toString() |
JTextField model entry |
modelField |
"Clio" (8 cols) |
JTextField power entry |
powerField |
"90" (5 cols) |
JTextField accel entry |
accelField |
"50" (5 cols) |
JCheckBox turbo mode |
turboCheck |
unchecked |
JButton Start |
startBtn |
enabled |
JButton Stop |
stopBtn |
enabled |
JButton Accelerate |
accelBtn |
enabled |
JButton Brake |
brakeBtn |
enabled |
JButton New Car |
newBtn |
enabled |
2.3 Behaviour
| Button | Action |
|---|---|
| Start | Call car.start(), call refresh() |
| Stop | Call car.stop(), call refresh() |
| Accelerate | Parse accelField → v; if Turbo is checked, v *= 2; call car.accelerate(v), call refresh(). If parse fails, show JOptionPane.showMessageDialog with an error |
| Brake | Parse accelField → v; call car.brake(v), call refresh() |
| New Car | Parse powerField, create new Car(modelField.getText(), p), call refresh(). If parse fails, show error dialog |
refresh() must update statusLabel with car.toString().
2.4 Skeleton
package com.s7infa3;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class CarUI extends JFrame {
private Car car = new Car("Clio", 90);
private JLabel statusLabel;
private JTextField modelField, powerField, accelField;
private JCheckBox turboCheck;
public CarUI() {
setTitle("Car Control");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout(8, 8));
buildNorth(); // TODO: status label
buildCenter(); // TODO: input fields
buildSouth(); // TODO: buttons
pack();
setLocationRelativeTo(null); // center on screen
}
private void buildNorth() {
// TODO: create statusLabel with car.toString()
// setBorder(BorderFactory.createEmptyBorder(8,8,8,8))
// add(statusLabel, BorderLayout.NORTH)
}
private void buildCenter() {
// TODO: GridLayout(2, 4, 8, 4) panel
// "Model:" + modelField, "Power:" + powerField
// "Accel:" + accelField, "Turbo:" + turboCheck
}
private void buildSouth() {
// TODO: FlowLayout panel, all 5 buttons
// Wire each button's ActionListener
}
private void refresh() {
// TODO: update statusLabel text with car.toString()
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() ->
new CarUI().setVisible(true));
}
}
2.5 Expected output
After clicking Start then Accelerate (value 50):
After clicking Brake (value 20):
After clicking Stop:
After entering model Polo, power 110 and clicking New Car:
Part 3 — Add a Menu (20 min)
Add a JMenuBar to your CarUI:
┌─────────────┬──────────────┐
│ File │ Help │
├─────────────┤ │
│ Save state │ About │
│ ─────────── │ │
│ Exit │ │
└─────────────┘
| Menu item | Behaviour |
|---|---|
| Save state | Print car.toString() to the console (file I/O from CM2 is optional) |
| Exit | System.exit(0) |
| About | Show JOptionPane.showMessageDialog with the text "Car Control v1.0\nStéphane Derrode — Centrale Lyon" |
private void buildMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
// TODO: add Save state and Exit items
JMenu helpMenu = new JMenu("Help");
// TODO: add About item
menuBar.add(fileMenu);
menuBar.add(helpMenu);
setJMenuBar(menuBar);
}
Call buildMenu() from the constructor before pack().
Part 4 — CarSelector — JComboBox (20 min)
Add a fleet selector to the window. The user can choose a pre-configured Car from a drop-down and the display updates instantly.
4.1 Pre-configured fleet
private Car[] fleet = {
new Car("Clio", 90),
new Car("Polo", 110),
new Car("Ferrari", 280),
};
private String[] names = {"Clio (90hp)", "Polo (110hp)", "Ferrari (280hp)"};
4.2 Add to CENTER panel
JComboBox<String> selector = new JComboBox<>(names);
selector.addActionListener(e -> {
car = fleet[selector.getSelectedIndex()];
refresh();
});
When the user selects an entry, the current car field is updated and the status label refreshes.
Part 5 — Exploration (remaining time)
5.1 Make the Accelerate button disabled (setEnabled(false)) when car.isStarted() is false, and re-enable it after Start. Use refresh() to keep the button state in sync.
5.2 Add a JSlider (range 0–200, initial value 50) that sets the acceleration value. When the slider moves, update accelField to show the current value.
5.3 Change the statusLabel text color to Color.GREEN when the car is started and Color.RED when stopped.
Deliverable
No formal submission. Verify all button behaviours before leaving.
Common Errors
| Error | Cause | Fix |
|---|---|---|
NumberFormatException |
Non-numeric text in powerField |
Wrap Integer.parseInt() in try/catch |
| Window is blank | setVisible(true) called before components added |
Move setVisible after pack() |
| Buttons have no effect | Listener not registered | Check addActionListener is called |
pack() gives tiny window |
No components have preferred sizes | Add content before calling pack() |
| Menu not showing | setJMenuBar() not called |
Call it on the JFrame, not on a JPanel |
| Accelerate seems stuck | Car not started, or already at maxSpeed() |
Click Start first; remember the speed is capped at 80 + power |