Java大作业(一)介绍了全部功能点
一、Main类——用于启动整个程序
......代码于Java大作业(二)
二、LoginWindowWindow类——用于登录
......代码于Java大作业(二)
三、FunctionSelectionWindow类——用于选择对应的功能
......代码于Java大作业(二)
四、AccountManagementWindow类——用于管理酒店工作人员账户
......代码于Java大作业(三)
五、RoomManagementWindow类——用于办理预定、入住、退房
......代码于Java大作业(四)
六、DiningManagementWindow类——用于预定餐饮
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class DiningManagementWindow extends JFrame {
private JTable table;
private DefaultTableModel model;
private List<String[]> foodData;
private String privilegePassword;
// 构建餐饮管理窗口,设置属性,读取菜品与权限密码数据,
// 布局界面,添加按钮及对应监听,展示后设为可见。
public DiningManagementWindow() {
setTitle("餐饮管理");
setSize(1200, 800);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
// 从文件中读取菜品数据
foodData = loadFoodDataFromFile();
privilegePassword = loadPrivilegePassword();
// 左侧显示酒店餐饮管理
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new GridBagLayout());
leftPanel.setBackground(Color.LIGHT_GRAY);
// 创建并设置标签
JLabel label = new JLabel("酒店餐饮管理", SwingConstants.CENTER);
label.setFont(new Font("Serif", Font.BOLD, 24));
// 使用 GridBagLayout 精确控制标签的位置
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = GridBagConstraints.CENTER; // 居中对齐
gbc.insets = new Insets(10, 10, 10, 10); // 内边距
leftPanel.add(label, gbc);
// 右侧显示餐饮信息
JPanel rightPanel = new JPanel(new BorderLayout());
// 餐饮表格
model = new DefaultTableModel(new Object[]{"序号", "菜品", "金额", "操作"}, 0);
table = new JTable(model);
table.getColumnModel().getColumn(3).setCellRenderer(new ButtonRenderer());
table.getColumnModel().getColumn(3).setCellEditor(new ButtonEditor(new JCheckBox()));
// 填充表格数据
for (String[] data : foodData) {
model.addRow(new Object[]{data[0], data[1], data[2], "预定"});
}
JScrollPane scrollPane = new JScrollPane(table);
rightPanel.add(scrollPane, BorderLayout.CENTER);
// 界面下方添加四个按钮
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
JButton modifyAmountButton = new JButton("修改金额");
JButton modifyNameButton = new JButton("修改菜名");
JButton addButton = new JButton("添加菜品");
JButton deleteButton = new JButton("删除菜品");
modifyAmountButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
modifyAmount();
}
});
modifyNameButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
modifyName();
}
});
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
addDish();
}
});
deleteButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
deleteDish();
}
});
buttonPanel.add(modifyAmountButton);
buttonPanel.add(modifyNameButton);
buttonPanel.add(addButton);
buttonPanel.add(deleteButton);
rightPanel.add(buttonPanel, BorderLayout.SOUTH);
// 使用 JSplitPane 将左侧标签和右侧表格分开
JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
splitPane.setDividerLocation(200); // 设置初始分隔条位置
splitPane.setOneTouchExpandable(false); // 禁用单击展开
splitPane.setResizeWeight(0.0); // 左侧部分不可调整大小
setContentPane(splitPane);
setVisible(true);
}
// 从 “Hotel management system/src/Food” 文件读数据,
// 按格式解析存进列表,遇异常打印栈信息并提示读取失败,最后返回列表。
private List<String[]> loadFoodDataFromFile() {
List<String[]> data = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader("Hotel management system/src/Food"))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
if (parts.length == 3) {
data.add(parts);
}
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "读取数据失败: " + e.getMessage());
}
return data;
}
// 尝试从 “Hotel management system/src/privilege_password” 文件读取权限密码,
// 失败则打印栈信息并提示,成功则返回读取内容。
private String loadPrivilegePassword() {
try (BufferedReader reader = new BufferedReader(new FileReader("Hotel management system/src/privilege_password"))) {
return reader.readLine();
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "读取权限密码失败: " + e.getMessage());
return "";
}
}
// 响应修改金额按钮,先选菜品,验证权限密码后获取新金额,
// 格式正确则更新表格并保存数据,有误则提示相应错误。
private void modifyAmount() {
int selectedRow = table.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(this, "请先选择一个菜品!");
return;
}
String currentAmount = (String) model.getValueAt(selectedRow, 2);
String inputPassword = JOptionPane.showInputDialog(this, "请输入权限密码:");
if (inputPassword == null || !inputPassword.equals(privilegePassword)) {
JOptionPane.showMessageDialog(this, "权限密码错误,您没有权限进行此操作!");
return;
}
String newAmount = JOptionPane.showInputDialog(this, "请输入新的金额:", currentAmount);
if (newAmount == null || newAmount.isEmpty()) {
return;
}
try {
double amount = Double.parseDouble(newAmount);
model.setValueAt(amount, selectedRow, 2);
saveFoodDataToFile();
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "请输入有效的金额!");
}
}
//针对修改菜名按钮点击,先选菜品,验证密码,
// 获取新菜名后更新表格并保存数据,没选菜品或密码错则相应提示。
private void modifyName() {
int selectedRow = table.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(this, "请先选择一个菜品!");
return;
}
String currentName = (String) model.getValueAt(selectedRow, 1);
String inputPassword = JOptionPane.showInputDialog(this, "请输入权限密码:");
if (inputPassword == null || !inputPassword.equals(privilegePassword)) {
JOptionPane.showMessageDialog(this, "权限密码错误,您没有权限进行此操作!");
return;
}
String newName = JOptionPane.showInputDialog(this, "请输入新的菜名:", currentName);
if (newName == null || newName.isEmpty()) {
return;
}
model.setValueAt(newName, selectedRow, 1);
saveFoodDataToFile();
}
// 响应添加菜品按钮,验证权限密码,
// 按规则依次输入并验证序号、菜名、金额,无误则添加到表格并保存菜品数据。
private void addDish() {
// 输入权限密码
String inputPassword = JOptionPane.showInputDialog(this, "请输入权限密码:");
if (inputPassword == null || !inputPassword.equals(privilegePassword)) {
JOptionPane.showMessageDialog(this, "权限密码错误,您没有权限进行此操作!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
// 从文件中读取数据
List<String[]> data = loadFoodDataFromFile();
// 输入新菜品的序号并验证
String newId = JOptionPane.showInputDialog(this, "请输入新菜品的序号:");
if (newId == null || newId.isEmpty()) {
JOptionPane.showMessageDialog(this, "序号不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
try {
int id = Integer.parseInt(newId);
// 检查序号是否重复
for (String[] entry : data) {
int existingId = Integer.parseInt(entry[0]);
if (existingId == id) {
JOptionPane.showMessageDialog(this, "序号重复,序号不能重复且需要按顺序", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
}
// 检查序号是否按顺序填写
if (!data.isEmpty()) {
int lastId = Integer.parseInt(data.get(data.size() - 1)[0]);
if (id != lastId + 1) {
JOptionPane.showMessageDialog(this, "序号不按顺序,序号必须是最后一个序号加1", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
}
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "请输入有效的序号!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
// 输入新菜品的名称并验证
String newName = JOptionPane.showInputDialog(this, "请输入新菜品的名称:");
if (newName == null || newName.isEmpty()) {
JOptionPane.showMessageDialog(this, "菜名不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
// 检查菜名是否重复
for (String[] entry : data) {
String existingName = entry[1];
if (existingName.equalsIgnoreCase(newName)) {
JOptionPane.showMessageDialog(this, "菜名重复,菜名不能重复", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
}
// 输入新菜品的金额并验证
String newAmount = JOptionPane.showInputDialog(this, "请输入新菜品的金额:");
if (newAmount == null || newAmount.isEmpty()) {
JOptionPane.showMessageDialog(this, "金额不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
try {
double amount = Double.parseDouble(newAmount);
// 添加新菜品
model.addRow(new Object[]{Integer.parseInt(newId), newName, amount, "预定"});
saveFoodDataToFile();
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "请输入有效的金额!", "错误", JOptionPane.ERROR_MESSAGE);
}
}
// 响应删除菜品操作,先选菜品,验证权限密码后从表格删行,重排行号,
// 再保存更新后的菜品数据到文件。
private void deleteDish() {
int selectedRow = table.getSelectedRow();
if (selectedRow == -1) {
JOptionPane.showMessageDialog(this, "请先选择一个菜品!");
return;
}
String inputPassword = JOptionPane.showInputDialog(this, "请输入权限密码:");
if (inputPassword == null || !inputPassword.equals(privilegePassword)) {
JOptionPane.showMessageDialog(this, "权限密码错误,您没有权限进行此操作!");
return;
}
model.removeRow(selectedRow);
renumberRows();
saveFoodDataToFile();
}
// 遍历表格模型的行,将每行序号列(第 1 列)的值更新为当前行索引加 1,
// 用于重新编排菜品序号,保证顺序正确。
private void renumberRows() {
for (int i = 0; i < model.getRowCount(); i++) {
model.setValueAt(i + 1, i, 0);
}
}
// 把表格模型中的菜品序号、名称、金额数据按格式
// 写入 “Hotel management system/src/Food” 文件,遇异常提示错误信息。
private void saveFoodDataToFile() {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("Hotel management system/src/Food"))) {
for (int i = 0; i < model.getRowCount(); i++) {
String id = model.getValueAt(i, 0).toString();
String name = model.getValueAt(i, 1).toString();
String amount = model.getValueAt(i, 2).toString();
writer.write(id + "," + name + "," + amount + "\n");
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "保存数据失败: " + e.getMessage());
}
}
// 弹出对话框让用户选顾客是否入住,
// 依选择分别展示对应预订菜品对话框,引导后续预订操作流程。
private void reserveDish(String dishName, double dishPrice) {
// 创建一个简单的对话框让用户选择顾客是否入住
int result = JOptionPane.showOptionDialog(
this,
"请选择顾客是否入住",
"预定菜品",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
new Object[]{"顾客已入住", "顾客未入住"},
"顾客未入住"
);
if (result == JOptionPane.YES_OPTION) {
showCheckInReservationDialog(dishName, dishPrice);
} else if (result == JOptionPane.NO_OPTION) {
showNoCheckInReservationDialog(dishName, dishPrice);
}
}
// 显示顾客已入住的预定对话框
private void showCheckInReservationDialog(String dishName, double dishPrice) {
JDialog dialog = new JDialog(this, "顾客已入住 - 预定菜品", true);
dialog.setMinimumSize(new Dimension(600, 400));
dialog.setPreferredSize(new Dimension(600, 400));
dialog.pack();
dialog.setLocationRelativeTo(this);
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 日期
JLabel dateLabel = new JLabel("日期:");
JTextField dateField = new JTextField();
// 姓名
JLabel nameLabel = new JLabel("姓名:");
JTextField nameField = new JTextField();
// 房号
JLabel roomNumberLabel = new JLabel("房号:");
JTextField roomNumberField = new JTextField();
// 状态
JLabel statusLabel = new JLabel("状态:");
JTextField statusField = new JTextField("已入住"); // 默认值为“已入住”
// 支付状态
JLabel paymentStatusLabel = new JLabel("支付状态:");
JTextField paymentStatusField = new JTextField("未支付");
// 提交按钮
JButton submitButton = new JButton("提交");
submitButton.addActionListener(e -> {
String date = dateField.getText();
String name = nameField.getText();
String roomNumber = roomNumberField.getText();
String status = statusField.getText();
String paymentStatus = paymentStatusField.getText();
if (date.isEmpty() || name.isEmpty() || roomNumber.isEmpty() || status.isEmpty()) {
JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!");
return;
}
saveReservation(true, date, roomNumber, name, dishName, dishPrice, status, paymentStatus);
dialog.dispose();
});
// 添加组件到面板
panel.add(dateLabel);
panel.add(dateField);
panel.add(nameLabel);
panel.add(nameField);
panel.add(roomNumberLabel);
panel.add(roomNumberField);
panel.add(statusLabel);
panel.add(statusField);
panel.add(paymentStatusLabel);
panel.add(paymentStatusField);
panel.add(submitButton);
// 设置对话框内容
dialog.setContentPane(panel);
dialog.setVisible(true);
}
// 显示顾客未入住的预定对话框
private void showNoCheckInReservationDialog(String dishName, double dishPrice) {
JDialog dialog = new JDialog(this, "顾客未入住 - 预定菜品", true);
dialog.setMinimumSize(new Dimension(600, 400));
dialog.setPreferredSize(new Dimension(600, 400));
dialog.pack();
dialog.setLocationRelativeTo(this);
JPanel panel = new JPanel(new GridLayout(0, 1));
panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 日期
JLabel dateLabel = new JLabel("日期:");
JTextField dateField = new JTextField();
// 姓名
JLabel nameLabel = new JLabel("姓名:");
JTextField nameField = new JTextField();
// 状态
JLabel statusLabel = new JLabel("状态:");
JComboBox<String> statusComboBox = new JComboBox<>(new String[]{"未入住", "已预定"});
// 支付方式
JLabel paymentMethodLabel = new JLabel("支付方式:");
JRadioButton onlinePaymentButton = new JRadioButton("线上支付");
JRadioButton cashPaymentButton = new JRadioButton("现金支付");
ButtonGroup paymentGroup = new ButtonGroup();
paymentGroup.add(onlinePaymentButton);
paymentGroup.add(cashPaymentButton);
// 提交按钮
JButton submitButton = new JButton("提交");
submitButton.addActionListener(e -> {
String date = dateField.getText().trim();
String name = nameField.getText().trim();
String status = (String) statusComboBox.getSelectedItem();
String paymentMethod = "";
if (date.isEmpty() || name.isEmpty() || status.isEmpty()) {
JOptionPane.showMessageDialog(dialog, "所有字段都必须填写!");
return;
}
if (onlinePaymentButton.isSelected()) {
paymentMethod = "线上支付";
} else if (cashPaymentButton.isSelected()) {
paymentMethod = "现金支付";
} else {
JOptionPane.showMessageDialog(dialog, "请选择支付方式!");
return;
}
// 保存预定信息
saveReservation(false, date, "", name, dishName, dishPrice, status, paymentMethod);
if (paymentMethod.equals("线上支付")) {
showOnlinePayment(dishPrice);
} else if (paymentMethod.equals("现金支付")) {
showCashPayment(dishPrice);
}
dialog.dispose();
});
// 添加组件到面板
panel.add(dateLabel);
panel.add(dateField);
panel.add(nameLabel);
panel.add(nameField);
panel.add(statusLabel);
panel.add(statusComboBox);
panel.add(paymentMethodLabel);
panel.add(onlinePaymentButton);
panel.add(cashPaymentButton);
panel.add(submitButton);
// 设置对话框内容
dialog.setContentPane(panel);
dialog.setVisible(true);
}
// 按入住状态选对应文件,构造含各预订信息的行数据,
// 写入文件,遇异常打印栈信息并提示保存预订信息失败。
private void saveReservation(boolean isCheckIn, String date, String roomNumber, String name, String dishName, double dishPrice, String status, String paymentInfo) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(isCheckIn ? "Hotel management system/src/Customeryrz" : "Hotel management system/src/Customerwrz", true))) {
int nextId = getNextId(isCheckIn);
StringBuilder lineBuilder = new StringBuilder();
// 写入 ID 和日期
lineBuilder.append(nextId).append(",");
lineBuilder.append(date).append(",");
// 写入房号(如果存在)
if (!roomNumber.isEmpty()) {
lineBuilder.append(roomNumber).append(",");
}
// 写入姓名(如果存在)
if (!name.isEmpty()) {
lineBuilder.append(name).append(",");
}
// 写入菜品名称
lineBuilder.append(dishName).append(",");
// 写入菜品价格
lineBuilder.append(dishPrice).append(",");
// 写入状态(如果存在)
if (!status.isEmpty()) {
lineBuilder.append(status).append(",");
}
// 写入支付信息(如果存在)
if (!paymentInfo.isEmpty()) {
lineBuilder.append(paymentInfo);
}
// 移除最后一个逗号(如果有)
if (lineBuilder.charAt(lineBuilder.length() - 1) == ',') {
lineBuilder.deleteCharAt(lineBuilder.length() - 1);
}
writer.write(lineBuilder.toString());
writer.newLine();
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "保存预定信息失败: " + e.getMessage());
}
}
// 依入住状态确定文件路径,读取文件中已有最大 ID,
// 在此基础上加 1 后返回,用于获取新预订记录的序号。
private int getNextId(boolean isCheckIn) {
String filePath = isCheckIn ? "Hotel management system/src/Customeryrz" : "Hotel management system/src/Customerwrz";
int nextId = 1;
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(",");
int currentId = Integer.parseInt(parts[0]);
if (currentId >= nextId) {
nextId = currentId + 1;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return nextId;
}
// 提示需支付金额,尝试展示微信支付二维码图片,
// 若失败则提示无法显示收款码,引导线上支付操作。
private void showOnlinePayment(double totalAmount) {
JOptionPane.showMessageDialog(this, "你需要支付 " + totalAmount + " 元。");
try {
ImageIcon icon = new ImageIcon("Hotel management system/src/weixinzhifuma.jpg");
JOptionPane.showMessageDialog(this, "请扫描二维码支付", "收款码", JOptionPane.INFORMATION_MESSAGE, icon);
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "无法显示收款码: " + e.getMessage());
}
}
//向用户提示需要支付的现金金额,
// 用于告知用户线下现金支付时应支付的具体费用情况。
private void showCashPayment(double totalAmount) {
JOptionPane.showMessageDialog(this, "你需要支付 " + totalAmount + " 元。");
}
// 按钮渲染器
private class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
// 按钮编辑器
private class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(e -> {
int row = table.convertRowIndexToModel(table.getEditingRow());
String dishName = (String) model.getValueAt(row, 1);
String dishPriceStr = (String) model.getValueAt(row, 2);
double dishPrice = Double.parseDouble(dishPriceStr);
reserveDish(dishName, dishPrice);
fireEditingStopped();
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
return button;
}
@Override
public Object getCellEditorValue() {
if (isPushed) {
// 这里可以添加按钮点击后的处理逻辑
System.out.println("Button clicked: " + label);
}
isPushed = false;
return new String(label);
}
@Override
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
@Override
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
}