Java使用多线程和GUI实现购买火车票<集合>

文章目录

  • 绪:
  • 样例
  • DEMO——购票项目
    • 项目要求
    • 实现步骤
      • 一、【车次.txt】【Person类】【Ticket类】
        • 1.【车次.txt】
        • 2.【Person类】
        • 3.【Ticket类】
      • 二、主窗口 【Window类】
        • 1、界面
        • 2、事件监听
          • 1.窗口加载就显示出信息
          • 2.查找按钮
          • 3. 刷新
          • 4.购买
      • 三、购买窗口【PayWindow类】
        • 1、界面
        • 2、实现线程接口【Runnable】
        • 3、事件监听
          • 1.提交信息
          • 2.下单
          • 3.窗口销毁
    • 源代码


绪:

  • 多线程与并发
  • 集合Map 、List
  • GUI(ecplise插件WindowBuilder)

样例

image-20210415143525182


DEMO——购票项目


项目要求

  1. 文本文件提供票的信息,车次、票价、始发站终点站、票数

  2. 启动程序,首先读取文件,放入TextArea中,如果车次较多,那么需要加滚动条(上述两步骤,用到的是文件读写IO)

  3. 输入车次,查找该车次,并显示信息

    如何在文本域中找出相关信息,并且读出这一条信息——字符串操作

  4. 找到车次了,输入购买张数,点击购买,弹出新的窗口——新的窗口是启动了一个线程——多线程

  5. 在购买界面,显示购买车次的信息,和顾客进行确认。并且提供身份证信息

    如果买多张,那么这些身份证信息,先保存到集合中(map),遍历集合,给每个身份证购买一张票

  6. 输出购买信息


实现步骤

需要创建一个车票javaBean类,和顾客javaBean类

来存储对应的车票信息和顾客信息


一、【车次.txt】【Person类】【Ticket类】

  • 【车次.txt】用来存储车票的信息

  • 【Person类】用来根据顾客的信息生成顾客的对象

  • 【Ticket类】生成车票的对象

【Person类】【Ticket类】都是两个JavaBean类


1.【车次.txt】

存储车票信息的.txt文件

K1528      石家庄      北  京      24.2      1
K1527      北  京      石家庄      24.2      2
K1526      石家庄      北  京      24.2      100
K1525      北  京      石家庄      24.2      200
K1524      石家庄      北  京      24.2      100
K1523      北  京      石家庄      24.2      200
K1522      石家庄      北  京      24.2      100
K1521      北  京      石家庄      24.2      200

2.【Person类】

用来根据顾客的信息生成顾客的对象

public class Person {private String name; // 姓名private String IDCard; // 身份证号private String ticketname; // 车票名private String start; // 起始站private String end; // 终点站private double price; // 车票的价钱public Person() {super();}public Person(String name, String iDCard) {super();this.name = name;IDCard = iDCard;}public Person(String name, String iDCard, String ticketname, String start, String end, double price) {super();this.name = name;IDCard = iDCard;this.ticketname = ticketname;this.start = start;this.end = end;this.price = price;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getIDCard() {return IDCard;}public void setIDCard(String iDCard) {IDCard = iDCard;}public String getTicketname() {return ticketname;}public void setTicketname(String ticketname) {this.ticketname = ticketname;}public String getStart() {return start;}public void setStart(String start) {this.start = start;}public String getEnd() {return end;}public void setEnd(String end) {this.end = end;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}@Overridepublic String toString() {return "Person [name=" + name + ", IDCard=" + IDCard + ", ticketname=" + ticketname + ", start=" + start+ ", end=" + end + ", price=" + price + "]";}}

3.【Ticket类】

生成车票的对象

public class Ticket {private String checi; // 车票名private String start; // 起始站private String end; // 终点站private double price; // 价格private int number; // 数量public Ticket(String checi, String start, String end, double price, int number) {super();this.checi = checi;this.start = start;this.end = end;this.number = number;this.price = price;}public Ticket(String checi, double price, int number) {super();this.checi = checi;this.price = price;this.number = number;}@Overridepublic String toString() {return "Ticket [checi=" + checi + ", start=" + start + ", end=" + end + ", price=" + price + ", number="+ number + "]\n";}public String getCheci() {return checi;}public void setCheci(String checi) {this.checi = checi;}public String getStart() {return start;}public void setStart(String start) {this.start = start;}public String getEnd() {return end;}public void setEnd(String end) {this.end = end;}public double getPrice() {return price;}public void setPrice(double price) {this.price = price;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}}

二、主窗口 【Window类】


1、界面

还需要弄个窗口显示信息,这里GUI用的Ecplise的【WindowsBuilder】

窗口的布局用的是【ABsolute layout】

控件拖动到界面就行了,进行调整一下就行了

image-20210415160826973

界面创建好之后,就需要添加对应的事件监听器了


2、事件监听

1.窗口加载就显示出信息

窗口加载就显示出车票信息

		/*** 窗口加载事件*/addWindowListener(new WindowAdapter() {@Overridepublic void windowOpened(WindowEvent e) {FileReader fr = null;BufferedReader br = null;try {// 1.用IO流读取【车次.txt】文件的信息fr = new FileReader(new File("src\\buyticket\\车次.txt"));br = new BufferedReader(fr);String checi = "	车 次	起始站	终点站	单价	票数\n";String str = null;while ((str = br.readLine()) != null) {// 2.拼接字符串,用来在textArea中展示信息checi += "	" + str + "\n";// 3.拆分字符串得到信息,创建 Ticket 对象String[] split = str.split("\t");Ticket tic = new Ticket(split[0], split[1], split[2], Double.parseDouble(split[3]),Integer.parseInt(split[4]));// 4.将生成的车票对象添加到 Map 集合里存储,Key-车次,Value-Ticket对象ticketMap.put(tic.getCheci(), tic);}// 5.textArea显示步骤 2得到的拼接字符串textArea.append(checi);} catch (Exception e1) {e1.printStackTrace();} finally {try {br.close();} catch (IOException e2) {e2.printStackTrace();}try {fr.close();} catch (IOException e2) {e2.printStackTrace();}}}});

2.查找按钮

根据文本框输入的信息查找相关车次

		/*** 查找按钮监听事件*/button_search.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent arg0) {// 1.清空textArea_1显示的信息textArea_1.setText("");// 2.获取文本框输入的信息String search = searchText.getText();String checi = "	车 次	起始站	终点站	单价	票数\n";// 3.遍历Map集合,比对信息Set<Map.Entry<String, Ticket>> entrySet = ticketMap.entrySet();for (Map.Entry<String, Ticket> entryset : entrySet) {// 3.1根据Map的键组成的集合比对从文本框得到的信息,如果Key包含有文本框的信息则获取对应的Value值,Ticket的对象if (entryset.getKey().contains(search)) {String key = entryset.getKey();Ticket tic = (Ticket) ticketMap.get(key);// 4.字符串拼接获取车票的信息checi += "	" + tic.getCheci() + "	" + tic.getStart() + "	" + tic.getEnd() + "	"+ tic.getPrice() + "	" + tic.getNumber() + "\n";}}// 5.textArea_1显示拼接的字符串textArea_1.append(checi);}});

3. 刷新

刷新车票信息的变化

		/*** 刷新*/shuaxin.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent arg0) {//1.将textArea显示的信息清空textArea.setText("");String checi = "	车 次	起始站	终点站	单价	票数\n";//2.遍历Map集合,获取Map中存储的车票信息Set<Map.Entry<String, Ticket>> entrySet = ticketMap.entrySet();for (Map.Entry<String, Ticket> set : entrySet) {Ticket tic = (Ticket) ticketMap.get(set.getKey());//3.字符串拼接checi += "	" + tic.getCheci() + "	" + tic.getStart() + "	" + tic.getEnd() + "	"+ tic.getPrice() + "	" + tic.getNumber() + "\n";}//4.textArea显示拼接之后的字符串textArea.append(checi);}});

注:这里可以优化下,自动定时刷新


4.购买

点击购买则弹出一个新的窗口【购买窗口】,这里就需要用到多线程,实现多个窗口同时运行

		/*** 点击购买*/button_buy.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent arg0) {//创建新的线程PayWindow pw = new PayWindow(ticketMap);new Thread(pw).start();}});

三、购买窗口【PayWindow类】


1、界面

和主窗口【Window类】一样,首先用【WindowBuilder】进行布局
image-20210415094406069

布好局之后就可以加事件监听了


2、实现线程接口【Runnable】

public class PayWindow extends JFrame implements Runnable {@Overridepublic void run() {PayWindow frame = new PayWindow(ticketMap);frame.setVisible(true);}
}

注:

这里为什么不用继承【Thread类】来实现线程类,大家可以知道,【PayWindow类】已经继承了【JFrame类】就不能再继承了,但是我们可以通过实现接口【Runnable】来实现线程类,这就是【Thread类】和【Runnable接口】在应用时的区别


3、事件监听


1.提交信息
  • 每提交一次有效信息则添加一次信息

  • 因为每个人的身份证号是唯一的,姓名可以重复,因此Map集合采用身份证号为Key,如果身份证号有重复则覆盖

  • textArea显示的信息中身份证号部分采用字符串截取

		/*** 提交按钮*/btnNewButton_subbmit.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent arg0) {// private String personlist1 = " 已提交信息名单\n 姓名 身份证号\n";// 1.设置textArea显示 personlist1 字符串,因为频繁使用,所以设置成了全局变量textArea.setText(personlist1);// 2.获取输入的姓名和身份证号String name = textField_name.getText();String IDCard = textField_IDCard.getText();String li = "";// 如果两个文本框不为空则添加信息到队列if (!"".equals(name) && !"".equals(IDCard)) {// 3.1用获取到的姓名和身份证号生成对象,添加到存储顾客对象的Map集合中	if(name.length()<=2) {name=name.charAt(0)+"  "+name.charAt(1);}Person person = new Person(name, IDCard);personMap.put(IDCard, person);} else {JOptionPane.showMessageDialog(null, name + IDCard + "信息不完整", name + IDCard, 0);}// 4.遍历Map集合,获取集合中顾客的所有信息Set<Map.Entry<String, Person>> set = personMap.entrySet();Iterator<Entry<String, Person>> setItor = set.iterator();while (setItor.hasNext()) {Person person = setItor.next().getValue();// 4.1将顾客的所有的信息拼接成字符串li += "  " + person.getName() +"	" + person.getIDCard().substring(0, 6) + "******"+ person.getIDCard().substring(14) + "\n";}// 5.textArea显示拼接的字符串textArea.append(li);}});

2.下单
  1. 判断顾客选择的车次存不存在
  2. 判断是否添加顾客的信息
  3. 判断车票数量是否小于购买数量
  4. 支付
  5. 购票
    1. 修改票的信息
    2. 如果车票卖完,但是还有顾客没买到票,则退钱
  6. 输出所有顾客信息
  7. 清空集合,以便下次提交信息
		/*** 下单按钮*/btnNewButton.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent arg0) {// 获取文本框输入的车次String checi = textField.getText();// 1.判断顾客选择的车次存不存在Ticket ticket = (Ticket) ticketMap.get(checi);if (ticket != null) {// 2. 判断是否添加顾客的信息int number = personMap.size();if (number > 0) {JOptionPane.showMessageDialog(null, "已提交信息名单为" + number, "已提交信息", 1);// 获取车次的信息String name = ticket.getCheci();String end = ticket.getEnd();String start = ticket.getStart();double price = ticket.getPrice();int ticketNumber = ticket.getNumber();// 用来接收对话框的返回值int n = 0;// 3.判断车票数量是否小于购买数量if (ticketNumber < number) {n = JOptionPane.showConfirmDialog(null,"车票剩余不够购买数量,目前剩余数量:" + ticketNumber + ",如果继续购买则先买先得", "",JOptionPane.YES_NO_OPTION);}if (n == 0) {// 4.支付int a = JOptionPane.showConfirmDialog(null,"按照已提交信息名单收取金额(若未购买到票则退还相应的金额),应支付金额:" + personMap.size() * price + ",是否确认支付","支付窗口", JOptionPane.YES_NO_OPTION);if (a == 0) {JOptionPane.showMessageDialog(null, "支付成功", checi, 1);textArea.setText(personlist2);String jine = "";// 5.购票 同步购票代码块,synchronized (PayWindow.class) {boolean bool = true;if (ticketNumber == 0) {bool = false;}// 统计购买了多少张票int count = 0;// 根据输入的信息循环购买多张票,如果票不够,则买完为止Set<Map.Entry<String, Person>> set = personMap.entrySet();Iterator<Entry<String, Person>> setItor = set.iterator();for (int i = 1; i <= personMap.size(); i++) {if (bool) {// 5.1修改票的信息Ticket tic = new Ticket(name, start, end, price, --ticketNumber);count++;if (setItor.hasNext()) {Person person = setItor.next().getValue();person.setTicketname(name);person.setPrice(price);}Window.ticketMap.put(name, tic);}jine = count * price + "";// 5.2如果车票卖完,但是还有顾客没买到票,则退钱if (ticketNumber == 0) {bool = false;ticketMap.remove(ticket.getCheci());JOptionPane.showMessageDialog(null, "票已售完,返还"+ (personMap.size() - count) * price + "总共花费" + count * price,"支付窗口", 1);break;}}}// 6.输出所有顾客信息Set<Map.Entry<String, Person>> set = personMap.entrySet();Iterator<Entry<String, Person>> setItor = set.iterator();String li = "";while (setItor.hasNext()) {Person person = setItor.next().getValue();// 截取字符串显示********li += "  " + person.getName() + "	" + person.getIDCard().substring(0, 6)+ "*******" + person.getIDCard().substring(14) + "	"+ person.getTicketname() + "	" + person.getPrice() + "\n";}textArea.append(li);textArea.append("				总共花费:" + jine);// 7.清空集合,以便下次提交信息personMap.clear();} else {JOptionPane.showMessageDialog(null, "支付失败", checi, 0);}} else {JOptionPane.showMessageDialog(null, checi + "票不够", checi, 0);}} else {JOptionPane.showMessageDialog(null, "未添加信息", checi, 0);}} else {JOptionPane.showMessageDialog(null, "未找到" + checi, checi, 0);}}});

3.窗口销毁

关闭购票窗口而不关闭整个程序

		// 设置窗口销毁,而不关闭程序addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {dispose();}});

源代码

Java用多线程GUI实现买车票【ticket.zip】

导入之后,更改导入包以及【车次.txt】文件路径

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1621668.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Python selenium实现全自动购买火车票

这个是实现结果&#xff0c;因为一天只能取消三次&#xff0c;所以最后一步点击确认被我注释了 1.首先实现使用selenium登陆12306 关于使用selenium实现12306登陆可以看我的另一篇文章 这里实现了使用selenium登陆12306&#xff0c;这次是基于上次的代码进行修改实现全自动购买…

【web测试】实战1:去哪儿网购买火车票|优化|po模式

【web测试】实战1&#xff1a;去哪儿网购买火车票|优化|po模式 测试用例设计1.项目计划2.测试用例 项目实战脚本基本代码优化代码重构base_function.pyqunaer_book.pytest_qunaer_book.pydata.xlsx po模式目录base.pyfunction.pybook_ticket_page.pybook_list_page.pybook_orde…

java购买火车票

题目要求&#xff1a;假设从A地到B地的火车票有硬座和硬卧&#xff0c;价格分别为100和190元。根据铁路部门规定&#xff0c;未成年人&#xff08;18周岁以下&#xff09;身高不足120cm免票&#xff0c;120&#xff08;含&#xff09;-150&#xff08;不含&#xff09;cm需半票…

Java购买火车票(初识并发)

初识并发&#xff08;购买火车票&#xff09; 购买火车票 发现问题&#xff1a;多个线程操作同一个资源的情况下&#xff0c;线程不安全&#xff0c;数据紊乱。 Code: public class TicketDemo_04 implements Runnable{private int ticketNumber 10; // 票数Overridepubli…

Spring注解之@validated的使用

使用步骤 1.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 2.异常拦截类 /*** 全局异常处理*/ Slf…

电视卡众说纷纭(二):2007年度市面常见电视卡软硬件性能

在查找VISTA MCE插件开发的过程中看到很多的是跟电视卡硬件相关的资料。看到最多的名词就是软压卡、硬压卡。一个好的软件开发人员不只是要了解软件的开发&#xff0c;对硬件的设施也应该有相关的了解。要不然就成了闭塞的书呆子。所以我整理了我看到的关于电视卡比较好帖子和文…

dasBlog-1.8.5223.1中文版

dasBlog-1.8.5223.1中文版 本版本的DasBlog是qihangnet基于dasBlog-1.8.5223.1原版做的本地化版本。安装提示&#xff1a;1、由于本系统是使用Asp.Net开发的&#xff0c;所以在安装前请确保您的服务器或者虚拟主机支持Asp.net&#xff1b;2、请确定您将要安装的目录&#xff0c…

关于Linux下ISE和vivado安装cable usb驱动的问题

由于先前安装Android Studio一直不成功&#xff0c;一气之下&#xff0c;本人重装了系统&#xff0c;导致之前装的驱动什么的都没有了&#xff0c;这时再安装vivado&#xff0c;检测不到驱动&#xff0c;这里介绍怎么安装cable usb的驱动&#xff0c;供参考。 要安装这个驱动&a…

如何用计算机观看电视节目,如何将计算机显示器变成电视以观看节目

2006-11-16 如何在计算机上观看电视&#xff1f;我喜欢NBA&#xff0c;我喜欢 对于初次接触电视卡的用户&#xff0c;安装和接收电视确实不是一件容易的事。为此&#xff0c;我们将以Winfast TV2000电视卡为例来说明此应用程序的具体步骤。实际上&#xff0c;不同品牌的电视卡使…

ElasticSearch(一)数据类型

ElasticSearch&#xff08;一&#xff09;数据类型 1.简述 Es数据类型分为基础数据类型和复杂类型数据&#xff0c;掌握ES数据类型才能进一步使用ES检索数据内容。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot…

无人驾驶领域的软件测试该如何开展?

无人驾驶汽车使用自主决策和控制系统&#xff0c;这种系统通常由多个软件和硬件组件组成。软件测试是必要的&#xff0c;因为它可以确保无人驾驶汽车的软件系统达到高度可靠性和安全性&#xff0c;以及提高无人驾驶汽车的性能和可靠性。 因此无人驾驶汽车是一定要进行严格的软件…

手写数字识别之网络结构

目录 手写数字识别之网络结构 数据处理 经典的全连接神经网络 卷积神经网络 手写数字识别之网络结构 无论是牛顿第二定律任务&#xff0c;还是房价预测任务&#xff0c;输入特征和输出预测值之间的关系均可以使用“直线”刻画&#xff08;使用线性方程来表达&#xff09…

[牛客复盘] 牛客周赛 Round 9 20230827

[牛客复盘] 牛客周赛 Round 9 20230827 总结小美的外卖订单编号1. 题目描述2. 思路分析3. 代码实现 小美的加法1. 题目描述2. 思路分析3. 代码实现 小美的01串翻转1. 题目描述2. 思路分析3. 代码实现 小美的数组操作1. 题目描述2. 思路分析3. 代码实现 六、参考链接 总结 又是…

数据分析基础-数据可视化学习笔记03-可视化的符号与表示-图形符号学

概念 图型符号学&#xff08;Cartographic Symbolization&#xff09;是地图学领域中的一个重要概念&#xff0c;涉及到如何使用不同的符号、颜色、图案和标记来在地图上表示地理信息和数据。图型符号学旨在传达地理信息&#xff0c;使得地图能够清晰、有效地传达各种空间数据…

DDT数据驱动测试

简单介绍 ​ DDT&#xff08;Date Driver Test&#xff09;&#xff0c;所谓数据驱动测试&#xff0c;简单来说就是由数据的改变从而驱动自动化测试的执行&#xff0c;最终引起测试结果的改变。通过使用数据驱动测试的方法&#xff0c;可以在需要验证多组数据测试场景中&#…

【80天学习完《深入理解计算机系统》】第十一天 3.5 过程(函数调用)

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

模板(二)

目录 非类型模板参数 引入 分类 使用typename的特殊情况 注意点 模板特化 引入 介绍 函数模板特化 使用 ​编辑 优点 类模板特化 全特化 偏特化 部分特化 特殊的特化 使用 分离编译 介绍 问题代码示例 代码 说明 预处理 编译 链接 类模板实例化…

期货量化软件:衡量指标信息

机器学习依靠数据训练来学习市场的一般行为&#xff0c;最终做出相当准确的预测。 所选学习算法必须遍历精心挑选的样本&#xff0c;以便提取有意义的信息。 许多人未能成功应用这些精密工具的原因是&#xff0c;大多数有意义的信息都隐藏在嘈杂的数据当中。 对于许多策略开发人…

期货量化交易软软件:怎样开发可以获利的交易策略

简介 通过技术分析开发成功交易策略的过程可以分为以下几步: ​ 编辑 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 在某个资产价格图表窗口上附加几个技术指标, 并识别出其中信号指标与市场关联的模式. 把上一步相关性分析取得的数据进行公式化. …

免费期货量化交易软件:种群优化算法引力搜索算法(GSA)

1. 概述 ​​​​​​​ 引力搜索算法&#xff08;GSA&#xff09;是由 E. Rashedi 提出的&#xff0c;用于解决优化问题&#xff0c;特别是非线性问题&#xff0c;它遵循牛顿的万有引力定律原理。 在所提议的算法中&#xff0c;粒子被视为物体&#xff0c;并在考虑其质量的情…