My university project is to create a working GUI for a car park application I made for an earlier project.
The car park is made up of staff parks and visitor parks, and the GUI creates buttons for each dynamically dependent on how many of each the user wants to add.
The problem I'm having is after I initially create my car park and take the user input for staff/visitor parks, the parks are displaying as intended, except clicking on each park for information doesn't work.
When I go through the option to 'Add Car' despite which slot I try to add car to, it only updates the final visitor park... eg if there are 5 staff and visitor parks, and I add a car to slot S001, the changes will reflect on slot V005.
PS. I'm pretty new to programming, so sorry if the format and logic isn't right. Also, we have to use the IDE called BlueJ, and for this project we aren't allowed to use any IDE that has a GUI creator in it.
Any tips would be greatly appreciated.
Thanks, Michael
The package consists of 4 classes: GUI, CarPark, ParkingSlot and Car.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.regex.*;
public class GUI extends JFrame
{
private JPanel panel;
private JButton but1;
private JButton but2;
private JButton but3;
private JButton but4;
private JButton but5;
private JButton but6;
private JButton button;
private static CarPark cp1 = new CarPark();
private static ParkingSlot ps = new ParkingSlot("", true, null);
public static final int YES_NO_OPTION = 0;
public static void main(String[] args)
{
JFrame myApp = new GUI();
myApp.setVisible(true);
}
public GUI()
{
//set size
super("Car Park Application");
createCarPark();
addButtons();
addListeners();
}
public void createCarPark()
{
JPanel staffFrame = new JPanel();
JPanel visitorFrame = new JPanel();
JPanel middle = new JPanel(new FlowLayout(FlowLayout.CENTER,100,10)); //panel to have staff/visitor parks
middle.add(staffFrame);
middle.add(visitorFrame);
add(middle, BorderLayout.CENTER);
// add a scrollpane
JScrollPane scrollPane = new JScrollPane(middle);
setPreferredSize(new Dimension(600, 400));
add(scrollPane, BorderLayout.CENTER);
int i = 0, j = 0;
String staffSlotNumber = "", visitorSlotNumber = "";
int staffSlots = Integer.parseInt(JOptionPane.showInputDialog(this,
"How many staff parks do you need?", "Create Staff Parks", 2));
int visitorSlots = Integer.parseInt(JOptionPane.showInputDialog(this,
"How many visitor parks do you need?", "Create Visitor Parks", 2));
JOptionPane.showMessageDialog(this,"Staff parks created: " + staffSlots +
"\nVisitor parks created: " + visitorSlots,
"Car Park Created!",JOptionPane.WARNING_MESSAGE );
//Create the actual car park
while (i < staffSlots)
{
if (i <9)
{
staffSlotNumber = "S00";
}
else if (i <99)
{
staffSlotNumber = "S0";
}
else if (i <999)
{
staffSlotNumber = "S";
}
else
{
JOptionPane.showMessageDialog(this,"No parks created. Exit and try again.",
"Massive error. Exit and try again.",JOptionPane.WARNING_MESSAGE );
}
ParkingSlot ps = new ParkingSlot(staffSlotNumber+(i+1), true, null);
cp1.addParkingSlot(ps);
button = new JButton(ps.toString());
staffFrame.add(button);
i++;
}
while (j < visitorSlots)
{
//
if (j <9)
{
visitorSlotNumber = "V00";
}
else if (j <99)
{
visitorSlotNumber = "V0";
}
else if (j <999)
{
visitorSlotNumber = "V";
}
else
{
JOptionPane.showMessageDialog(this,"No parks created. Exit and try again.",
"Massive error. Exit and try again.",JOptionPane.WARNING_MESSAGE );
}
//
ParkingSlot ps = new ParkingSlot(visitorSlotNumber+(j+1), false, null);
cp1.addParkingSlot(ps);
button = new JButton(ps.toString());
visitorFrame.add(button);
j++;
}
staffFrame.setLayout(new GridLayout(staffSlots,1));
visitorFrame.setLayout(new GridLayout(visitorSlots,1));
setSize(1200,600);
setVisible(true);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void addButtons()
{
but1 = new JButton("Add Car");
but2 = new JButton("Remove Car");
but3 = new JButton("Find Car");
but4 = new JButton("Add Car Park");
but5 = new JButton("Remove Car Park");
but6 = new JButton("Exit");
JPanel buttonPanel = new JPanel( );
buttonPanel.setLayout(new GridLayout(2,3));
buttonPanel.add(but1);
buttonPanel.add(but2);
buttonPanel.add(but3);
buttonPanel.add(but4);
buttonPanel.add(but5);
buttonPanel.add(but6);
add(buttonPanel, BorderLayout.SOUTH);
}
public void addListeners()
{
//add listeners
but1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
addCar();
}
});
but2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
removeCar();
}
});
but3.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
findCar();
}
});
but4.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
addPark();
}
});
but5.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
removePark();
}
});
but6.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
exitApp();
}
});
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
button.setText(ps.toString());
}
});
pack();
}
public void addCar()
{
boolean staff;
String staffStr;
String carRego = "";
do
{
carRego = JOptionPane.showInputDialog(this,
"Please input a registration to add.\nUse format A12345", "Add Car - Registration", 3);
} while (!Pattern.matches("[A-Z]{1}[0-9]{5}", carRego));
String driverName = JOptionPane.showInputDialog(this,
"What is the driver's name?", "Add Car - Driver's Name", 3);
//send carRego to the CarPark class
String slotId = "";
do
{
slotId = JOptionPane.showInputDialog(this,
"Please input a slot ID.\nUse format S001", "Add Car - Slot ID", 3);
} while (!slotId.matches("[SV][0-9][0-9][0-9]"));
//if (slotId.charAt(0) == 'S')
int choice = JOptionPane.showConfirmDialog(this,
"Is this person a staff member?", "Staff Member?", JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION)
{
staff = true;
staffStr = "They are a staff member.";
} else
{
staff = false;
staffStr = "They are a visitor.";
}
JOptionPane.showMessageDialog(this,"You have entered the registration: " + carRego +
"\nYou have entered the name: " + driverName +
"\nYou have entered the slot ID: " + slotId +
"\n" + staffStr,
"Registration and Slot ID Confirmation",JOptionPane.INFORMATION_MESSAGE );
Car car = new Car(carRego, driverName, staff);
ParkingSlot ps;
ps = cp1.findParkingSlot(slotId);
//staff-visitor check
if (ps == null)
{
//System.out.println("Please pick an existing car space.");
JOptionPane.showMessageDialog(
this,
"Please pick an existing car space.",
"Park doesn't exist.",
JOptionPane.PLAIN_MESSAGE);
}
else if (ps.hasCar())
{
//System.out.println("There is already a car in that place.");
JOptionPane.showMessageDialog(
this,
"There is already a car in that place.",
"Park doesn't exist.",
JOptionPane.PLAIN_MESSAGE);
}
else if (ps.getStaffPark() == true && staff == false)
{
//System.out.println("You cannot put a visitor in a staff park.");
JOptionPane.showMessageDialog(
this,
"You cannot put a visitor in a staff park.",
"Park doesn't exist.",
JOptionPane.PLAIN_MESSAGE);
}
else if (ps.getStaffPark() == false && staff == true)
{
//System.out.println("You cannot put staff in a visitor park.");
JOptionPane.showMessageDialog(
this,
"You cannot put staff in a visitor park.",
"Park doesn't exist.",
JOptionPane.PLAIN_MESSAGE);
}
else
{
//successful details are stored and output.
ps.setSlotNumber(slotId);
ps.setStaffPark(staff);
ps.parkCar(car);
button.setText(ps.toString());
revalidate();
repaint();
JOptionPane.showMessageDialog(
this,
"Success!\nYou added: " + carRego + " to park " + slotId + "." ,
"Parking Spot Addition",
JOptionPane.PLAIN_MESSAGE);
}
}
public void removeCar()
{
String carRego = "";
do
{
carRego = JOptionPane.showInputDialog(this,
"Which registration? Use format A12345", "Remove Car", 3);
} while (!carRego.matches("[A-Z][0-9]{5}"));
ParkingSlot ps = cp1.findCar(carRego);
if (ps != null)
{
ps.removeCar();
JOptionPane.showMessageDialog(this,"You have REMOVED the registration: " + carRego,
"Registration Removal Confirmation",JOptionPane.WARNING_MESSAGE );
}
else
{
JOptionPane.showMessageDialog(this,"Car registration " + carRego + " does not exist.",
"Registration Removal Failure",JOptionPane.WARNING_MESSAGE );
}
}
public void findCar()
{
//declare variables
String carRego = "";
String slotNumber;
ParkingSlot ps;
//prompt user with registration format check
do
{
carRego = JOptionPane.showInputDialog(this,
"Please enter car registration (eg A12345):", "Find Car", 2);
} while (!carRego.matches("[A-Z][0-9]{5}"));
//find car rego in carpark array list
ps = cp1.findCar(carRego);
//check for incorrect format/inputs
if(ps == null)
{
JOptionPane.showMessageDialog(this,"Car registration " + carRego + " does not exist.",
"Find Car - Unsuccessful",JOptionPane.WARNING_MESSAGE );
}
else
{
JOptionPane.showMessageDialog(this, "Success, the car has been found!\nOwner: "+ ps.getCar().getName()
+ "\nRegistration: " + ps.getCar().getRego()
+ "\nCar park location: [" + ps.getSlotNumber() + "]",
"Find Car - Successful",JOptionPane.WARNING_MESSAGE );
}
}
public void addPark()
{
String slotNumber = "";
do
{
slotNumber = JOptionPane.showInputDialog(this,
"Please input a new car park ID to add to the car park eg S001", "Add a new slot ID", 2);
} while (!slotNumber.matches("[SV]\\d\\d\\d"));
JOptionPane.showMessageDialog(this,"You have ADDED to the car park: " + slotNumber,
"Add a new parking spot",JOptionPane.INFORMATION_MESSAGE );
ParkingSlot ps;
Car car = null;
boolean staff;
if (slotNumber.toUpperCase().charAt(0) == 'S')
{
staff = true;
}
else
{
staff = false;
}
ps = cp1.findParkingSlot(slotNumber);
if (ps != null)
{
JOptionPane.showMessageDialog(this,"This parking slot number already exists. Choose another."
+ slotNumber,"Add a new parking spot",JOptionPane.INFORMATION_MESSAGE );
return;
}
else
{
cp1.addParkingSlot(new ParkingSlot(slotNumber,staff, car));
JOptionPane.showMessageDialog(this,"Sucess! You have added slot: "
+ slotNumber,"Add a new parking spot",JOptionPane.INFORMATION_MESSAGE );
}
//System.out.println("New slot " + slotNumber + " has been added to the car park.");
System.out.println(cp1.toString());
}
public void removePark()
{
String slotNumber;
ParkingSlot ps;
do
{
slotNumber = JOptionPane.showInputDialog(this,
"Please input an existing parking spot to REMOVE from the car park", "Remove Park", 2);
//System.out.println("Which park would you like to remove? Enter slot number");
//slotNumber = input.nextLine();
} while (!slotNumber.matches("[SV]\\d\\d\\d"));
ps = cp1.findParkingSlot(slotNumber);
if (ps != null)
{
if (ps.hasCar())
{
JOptionPane.showMessageDialog(this,"The parking slot is occupied, you cannot remove it.",
"Remove Park - Unsuccessful",JOptionPane.WARNING_MESSAGE );
//System.out.println("The parking slot is occupied, you cannot remove it.");
}
else
{
cp1.removeParkingSlot(ps);
JOptionPane.showMessageDialog(this,"Parking slot :" + slotNumber
+ " was vacant, and has been removed.",
"Remove park - Successful",JOptionPane.WARNING_MESSAGE );
//System.out.println("Parking slot " + slotNumber + " was vacant, and has been removed.");
}
}
else
{
JOptionPane.showMessageDialog(this,"The parking slot doesn't exist",
"Remove Park - Unsuccessful",JOptionPane.WARNING_MESSAGE );
//System.out.println("Unable to perform action. That parking slot does not exist");
}
if (cp1.numberOfparks() == 0)
{
JOptionPane.showMessageDialog(this,"All parks removed",
"Remove Park - Successful",JOptionPane.WARNING_MESSAGE );System.out.println("All parks have been removed.");
}
}
public void exitApp()
{
System.exit(0);
}
}
import java.util.ArrayList;
public class CarPark {
public ArrayList<ParkingSlot> parks;
public CarPark()
{
parks = new ArrayList<ParkingSlot>();
}
public ArrayList<ParkingSlot> getParks()
{
return parks;
}
public String toString()
{
String parkingString = "";
for (ParkingSlot parkingSlot : parks)
{
parkingString += parkingSlot.toString() + "\n";
}
if (parkingString.equals(""))
{
parkingString = "No parking spots exist.";
}
return parkingString;
}
public void addParkingSlot(ParkingSlot parkingSlot)
{
parks.add(parkingSlot);
}
public void removeParkingSlot(ParkingSlot parkingSlot)
{
parks.remove(parkingSlot);
}
public int numberOfparks()
{
return parks.size();
}
public ParkingSlot findParkingSlot(String slotNumber)
{
for (ParkingSlot parkingSlot : parks)
{
if (parkingSlot.getSlotNumber().equals(slotNumber))
{
return parkingSlot;
}
}
return null;
}
public ParkingSlot findCar(String findRego)
{
ParkingSlot ps = null;
for(int i = 0; i < parks.size(); i++)
{
ps = parks.get(i);
// check to see if there's a car object in a park.
Car car = ps.getCar();
if(car != null && findRego.equals(car.getRego()))
return ps;
}
return null;
}
}
public class ParkingSlot
{
//variables required for parking slot.
private String slotNumber;
private boolean staffPark;
private Car car;
public ParkingSlot(String slotNumber, boolean staffPark, Car car)
{
this.slotNumber = slotNumber;
this.staffPark = staffPark;
this.car = null;
}
public String getSlotNumber()
{
return slotNumber;
}
public void setSlotNumber(String newSlotNumber)
{
slotNumber = newSlotNumber;
}
public boolean getStaffPark()
{
return staffPark;
}
public void setStaffPark(boolean newStaffPark)
{
staffPark = newStaffPark;
}
public Car getCar()
{
return car;
}
public void parkCar(Car car)
{
this.car = car;
}
public void removeCar()
{
car = null;
}
public boolean hasCar()
{
return this.car != null;
}
public String toString()
{
//String staffOrVisitor = "] [ Staff Park ] ";
String staffOrVisitor = "Park: ";
String taken = "is taken";
if (staffPark == false)
{
//staffOrVisitor = "] [Visitor Park] ";
staffOrVisitor = "Park: ";
}
if (car == null)
{
taken = " [vacant]";
}
else
{
taken = " contains vehicle, registration [" + car.getRego() + "]";
}
return staffOrVisitor + slotNumber + taken;
// return "Park [" + slotNumber + staffOrVisitor + taken;
}
}
public class Car {
// instance variables
private String rego;
private String name;
private boolean staff;
public Car(String rego, String name, boolean staff)
{
this.rego = rego;
this.name = name;
this.staff = staff;
}
public String toString()
{
return "Registration " + rego + " - Name: " + name + " - Staff member: " + staff;
}
public String getRego(){
return rego;
}
public void setRego(String newRego){
rego = newRego;
}
public String getName(){
return name;
}
public void setName(String newName){
name = newName;
}
public boolean getStaff(){
return staff;
}
public void setStaff(boolean newStaff){
staff = newStaff;
}
}
Again, the issue is creating a model and somehow tying it to your view (the GUI). Best is to create and maintain good separation between these two classes or groups of classes, but to keep things simpler in this instance, we can combine them in the GUI. To show you what I mean, consider this simplification of your code, one that uses very simple Car and ParkingSlot classes:
public class Car {
private String name;
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Car: " + name;
}
}
public class ParkingSlot {
private Car car;
private String name;
public ParkingSlot(String name) {
this.name = name;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public void clear() {
car = null;
}
public String getName() {
return name;
}
@Override
public String toString() {
String value = "Slot: " + name + "; ";
if (car == null) {
value += "empty";
} else {
value += car.toString();
}
return value;
}
}
I want a model that ties a String to a ParkingSlot, and for this, best is to use a Map<String, ParkingSlot>
. This is a collection that holds ParkingSlot objects and makes them accessable by the slot's "name", the String. I would often initialize this as a new HashMap<String, ParkingSlot>()
, but I also want to maintain insertion order in the Map so that if I iterate through it, it is not in some random order (as HashMaps tend to be), and so, I'd initialize this using a LinkedHashMap<String, ParkingSlot>
, since this is just like a HashMap but retains insertion order:
private Map<String, ParkingSlot> slotMap = new LinkedHashMap<>();
And so, if later I want to iterate through the collection, display the status of the ParkingSlot objects, I could simply use a for loop:
for (Entry<String, ParkingSlot> entry : slotMap.entrySet()) {
System.out.printf("%s%n", entry.getValue());
}
So, now when creating your JButton grid, associate it with the collection of ParkingSlot objects, using the String that defines the slot. This can be the key
for the Map
and also can be associated with the JButton by using it to set the button's actionCommand, a String that every button carries with it:
JPanel gridPanel = new JPanel(new GridLayout(0, 1));
for (int i = 0; i < slotCount; i++) {
String slotName = String.format("V%03d", i);
ParkingSlot slot = new ParkingSlot(slotName);
slotMap.put(slotName, slot);
JButton button = new JButton(slotName + ": Empty");
button.setActionCommand(slotName);
button.addActionListener(e -> parkingSlotButtonAction(e));
gridPanel.add(button);
}
When any of the buttons are pressed, the parkingSlotButtonAction(ActionEvent e)
method is called, and it can get the source JButton by calling e.getSource()
on the parameter, and can get the button's actionCommand by calling e.getActionCommand()
on the same parameter. It can get the associated ParkingSlot object by using the slotMap
:
private void parkingSlotButtonAction(ActionEvent e) {
String slotName = e.getActionCommand();
JButton source = (JButton) e.getSource();
ParkingSlot slot = slotMap.get(slotName);
// .....
}
A complete simple example could look like this:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.*;
import javax.swing.event.ChangeListener;
public class SimpleLotMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
LotGui gui = new LotGui(20);
JFrame frame = new JFrame("Lot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(gui);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
@SuppressWarnings("serial")
class LotGui extends JPanel {
private Map<String, ParkingSlot> slotMap = new LinkedHashMap<>();
public LotGui(int slotCount) {
JPanel gridPanel = new JPanel(new GridLayout(0, 1));
for (int i = 0; i < slotCount; i++) {
String slotName = String.format("V%03d", i);
ParkingSlot slot = new ParkingSlot(slotName);
slotMap.put(slotName, slot);
JButton button = new JButton(slotName + ": Empty");
button.setActionCommand(slotName);
button.addActionListener(e -> parkingSlotButtonAction(e));
gridPanel.add(button);
}
JScrollPane scrollPane = new JScrollPane(gridPanel);
scrollPane.getViewport().setPreferredSize(new Dimension(400, 400));
JButton displaySlotsBtn = new JButton("Display Parking Spots");
displaySlotsBtn.addActionListener(e -> displaySlots());
JPanel bottomPanel = new JPanel();
bottomPanel.add(displaySlotsBtn);
setLayout(new BorderLayout());
add(scrollPane);
add(bottomPanel, BorderLayout.PAGE_END);
}
private void parkingSlotButtonAction(ActionEvent e) {
String slotName = e.getActionCommand();
JButton source = (JButton) e.getSource();
ParkingSlot slot = slotMap.get(slotName);
// JOptionPane to query whether to add/remove car
String carName = JOptionPane.showInputDialog("Enter Name of Car to Add");
// if the user cancels the dialog or enters only white-space text: exit
if (carName == null || carName.trim().isEmpty()) {
return;
}
// else, use the name
Car car = new Car(carName);
slot.setCar(car);
String text = slotName + ": " + carName;
source.setText(text);
}
private void displaySlots() {
for (Entry<String, ParkingSlot> entry : slotMap.entrySet()) {
System.out.printf("%s%n", entry.getValue());
}
}
}
//class SLot {
// List<ParkingSlot> slots = new ArrayList<>();
//
// public SLot(int carCount) {
// for (int i = 0; i < carCount; i++) {
// String name = String.format("S%03d", i);
// slots.add(new ParkingSlot(name));
// }
// }
//
// @Override
// public String toString() {
// return "SLot [slots=" + slots + "]";
// }
//
// public void addChangeListener(ChangeListener l) {
//
// }
//}
class Car {
private String name;
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Car: " + name;
}
}
class ParkingSlot {
private Car car;
private String name;
public ParkingSlot(String name) {
this.name = name;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public void clear() {
car = null;
}
public String getName() {
return name;
}
@Override
public String toString() {
String value = "Slot: " + name + "; ";
if (car == null) {
value += "empty";
} else {
value += car.toString();
}
return value;
}
}