Java Swing GUI创建-如何让动态创建的按钮正确更新



我的大学项目是为我为早期项目制作的停车场应用程序创建一个可工作的GUI。

停车场由员工停车场和游客停车场组成,GUI根据用户想要添加的按钮数量动态地为每个停车场创建按钮。

我遇到的问题是,在我最初创建停车场并接受员工/游客停车场的用户输入后,停车场按预期显示,只是点击每个停车场获取信息无效。

当我选择"添加汽车"时,无论我试图将汽车添加到哪个位置,它只会更新最终的游客停车场。。。例如,如果有5个工作人员和游客停车场,我在S001停车位增加了一辆车,这些变化将反映在V005停车位上。

PS。我对编程还很陌生,如果格式和逻辑不正确,我很抱歉。此外,我们必须使用名为BlueJ的IDE,对于这个项目,我们不允许使用任何有GUI创建者的IDE

如有任何提示,我们将不胜感激。

谢谢,Michael

该软件包由4个类组成:GUI、CarPark、ParkingSlot和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;
}
}

同样,问题是创建一个模型并以某种方式将其绑定到视图(GUI(。最好是在这两个类或类组之间创建并保持良好的分离,但在这种情况下,为了使事情更简单,我们可以在GUI中组合它们。为了向您展示我的意思,请考虑代码的简化,它使用了非常简单的Car和ParkingSlot类:

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;
}
}

我想要一个将String绑定到ParkingSlot的模型,为此,最好使用Map<String, ParkingSlot>。这是一个保存ParkingSlot对象的集合,并使它们可由插槽的"访问;name";,字符串。我经常将其初始化为new HashMap<String, ParkingSlot>(),但我也希望在Map中保持插入顺序,这样,如果我对其进行迭代,它就不会按照某种随机顺序(就像HashMaps倾向的那样(,因此,我会使用LinkedHashMap<String, ParkingSlot>来初始化它,因为这与HashMap一样,但保留了插入顺序:

private Map<String, ParkingSlot> slotMap = new LinkedHashMap<>();

因此,如果以后我想遍历集合,显示ParkingSlot对象的状态,我可以简单地使用for循环:

for (Entry<String, ParkingSlot> entry : slotMap.entrySet()) {
System.out.printf("%s%n", entry.getValue());
}

因此,现在在创建JButton网格时,使用定义插槽的String将其与ParkingSlot对象的集合相关联。这可以是Mapkey,也可以通过使用它来设置按钮的actionCommand与JButton相关联,每个按钮都携带一个字符串:

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);
}

当按下任何按钮时,都会调用parkingSlotButtonAction(ActionEvent e)方法,它可以通过对参数调用e.getSource()来获取源JButton,也可以通过对同一参数调用e.getActionCommand()来获取按钮的actionCommand。它可以使用slotMap:获取关联的ParkingSlot对象

private void parkingSlotButtonAction(ActionEvent e) {
String slotName = e.getActionCommand();
JButton source = (JButton) e.getSource();
ParkingSlot slot = slotMap.get(slotName);

// .....
}

一个完整的简单例子可以是这样的:

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;
}
}

最新更新