基于SWT的图书管理系统设计

news2024/11/24 20:52:51

功能说明

用SWT做一个图书管理系统,要求实现如下功能:

用户从登录窗口登录。用户身份有3种:高级管理员,普通管理员,普通用户。权限如下:

高级管理员具有所有权限,包括增、删、改、查书籍和用户,借书和还书,设置借阅数量限制,查看所有人的借阅记录;

普通管理员只能增、删、改、查书籍,借书,还书,查看所有人的借阅记录;

普通用户只能借书和还书,查看自己的借阅记录。

所有用户和书籍均有正常和冻结两种状态。

高级管理员可以设置所有用户和书籍的状态,普通管理员只可以设置书籍的状态。

被冻结的用户只能进行还书和查询操作,被冻结的书籍只能被还而不能被借。

架构设计

数据表

使用MySQL建立library数据库,创建5个表:

表books存储所有书籍的信息,包括ISBN(唯一标识)、书名、作者、书籍类型(文学、科学等)、出版社、出版日期、馆藏总数、借出数量、未借出数量、书籍状态(正常或冻结)和添加日期;

表users存储所有用户(包括高级管理员,普通管理员和普通用户)的信息,包括用户名、姓名、登录密码、身份类型(上述三种身份之一)、用户状态(正常或冻结)和添加日期;

表records存储用户的借还记录信息,包括操作时间、用户名、姓名、ISBN、书名、操作类型(借阅或归还)和操作数量;

表states存储用户借还书籍的状态信息,包括用户名、姓名、ISBN、书名、共借过该本书的数量、已还数量、未还数量。这里用户名和ISBN共同确定一条记录,某用户多次借还该本书会以累加的计算方法改变该条记录;

表settings只存储两个数,最大允许借阅总数和单本最大允许借阅数量,只能由高级管理员设置。

各个表的字段信息设置如下:

books字段设置:

下面是分行展示的books的几条记录:

 users字段设置:

books的几条记录:

records字段设置:

records的几条记录:

 states字段设置:

states的几条记录:

settings字段设置:

settings存储的记录:

UI

所有用户共用一个登录窗口,根据所输入的用户名是否存储在users表中及密码是否正确来决定是否允许登录。登录时从users表获取用户的身份,不同身份有不同的展示项。

高级管理员界面展示所有书籍、所有用户、所有借阅状态、我的借阅状态四个表格界面,这里通过SWT中的扩展栏实现四个界面的切换展示。

所有书籍和所有用户界面提供增删改查按钮,所有借阅状态和我的借阅状态只提供查找按钮,其表格内容由用户的操作自动存入数据库,不能更改。借阅记录详情通过表格的上下文菜单弹出。

高级管理员界面同时展示设置、更新、返回登录界面、退出四个按钮。设置按钮用于设置用户的最大可借阅总数和最大单本可借阅数量;更新按钮用于当进行增删改查操作后更新展示的信息。

 

普通管理员展示所有书籍、所有借阅状态和我的借阅状态三项:

普通用户只展示所有书籍和我的借阅状态两项:

 图书借还功能通过选中书籍表格行时右键弹出的上下文菜单提供。图书和登录用户的状态不同,右键菜单也不同。图书和登录用户有任一个冻结时,不弹出借阅按钮。图书未被登录用户借阅时,不弹出归还按钮。

当点击添加、删除、修改、借阅和归还按钮时,弹出相应的操作面板:

 点击查找按钮,弹出响应的查询面板,其中可以通过设置一些条件筛选:

类实现 

考虑到上述界面有大量的共同点,因此通过类来实现,通过传入不同的构造参数即可展示不同的面板。

这里建立MainUI类,不同身份的用户登录时,传入的构造参数决定了展示哪些表格和按钮项;

建立OperationComposition类,继承Composition类,用于在扩展项中包含操作按钮和表格;

建立ExtendedTable类,继承Table类,根据传入的构造参数(包括要展示的数据等)绘制表格,类中还会根据登录用户的身份选择在表格上弹出哪些上下文菜单;

 建立OperationPanel类,用于点击增、删、改和借还按钮时弹出面板,构造参数包括要展示的输入项等;

建立SearchUI类,用于点击查找按钮时弹出查询面板,可以设置一些查询条件。SearchUI类中构造了ExtendedTable对象用于展示查询到的表格数据。

关键部分代码:

登录界面LoginShell:
protected void createContents(){

		loginShell = new Shell();
		loginShell.setSize(314, 187);
		loginShell.setText("\u767B\u5F55");
		loginShell.setMaximumSize(314, 187);
		loginShell.setMinimumSize(314, 187);
		
		Label label = new Label(loginShell, SWT.NONE);
		label.setBounds(31, 23, 40, 17);
		label.setText("\u8D26\u53F7");
		
		Label lblNewLabel = new Label(loginShell, SWT.NONE);
		lblNewLabel.setBounds(31, 69, 40, 17);
		lblNewLabel.setText("\u5BC6\u7801");
		
		Account_textField = new Text(loginShell, SWT.BORDER);
		Account_textField.setText("");
		Account_textField.setBounds(80, 20, 163, 23);
		
		Password_textField = new Text(loginShell, SWT.BORDER | SWT.PASSWORD);
		Password_textField.setText("");
		Password_textField.setBounds(80, 66, 163, 23);
		
		try {
			connection=DriverManager.getConnection("jdbc:mysql://localhost/Library","scott","tiger");
			statement=connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		
		Button LoginButton = new Button(loginShell, SWT.NONE);
		LoginButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e){
				//连接数据库
				try {					
					account=Account_textField.getText();
					password=Password_textField.getText();
					ResultSet resultSet=statement.executeQuery("select userpassword,userrole from users where userAccount='"+account+"'");
					resultSet.next();
					String queried_role;
					if(!account.equals("")) {
						if(!password.equals("")) {
							if(resultSet.getString(1).equals(password)) {
								switch (resultSet.getString(2)) {
								case "高级管理员":
									MainUI mainUI=new MainUI(account,"高级管理员",new String[] {"所有书籍","所有用户","所有借阅状态","我的借阅状态"},statement);
									break;
								case "普通管理员":
									mainUI=new MainUI(account,"普通管理员",new String[] {"所有书籍","所有借阅状态","我的借阅状态"},statement);
									break;
								case "普通用户":
									mainUI=new MainUI(account,"普通用户",new String[] {"所有书籍","我的借阅状态"},statement);
									break;
								default:
									break;
								}
								loginShell.close();
								MainUI.main(null);																
							}
							else {
								MessageBox messageBox=new MessageBox(loginShell,SWT.ICON_INFORMATION|SWT.OK);
								messageBox.setText("提示");
								messageBox.setMessage("用户名或密码错误,请重新输入!");
								int message=messageBox.open();
							}
						}
						else {
							MessageBox messageBox=new MessageBox(loginShell,SWT.ICON_INFORMATION|SWT.OK);
							messageBox.setText("提示");
							messageBox.setMessage("密码不能为空!");
							int message=messageBox.open();
						}
					}
					else {
						MessageBox messageBox=new MessageBox(loginShell,SWT.ICON_INFORMATION|SWT.OK);
						messageBox.setText("提示");
						messageBox.setMessage("用户名不能为空!");
						int message=messageBox.open();
						//e.doit=message==SWT.YES;
						return ;
					}
				} catch (Exception e2) {
					// TODO: handle exception
					e2.printStackTrace();
				}
			}
		});
		LoginButton.setBounds(31, 106, 80, 27);
		LoginButton.setText("\u767B\u5F55");
		
		Button CancelButton = new Button(loginShell, SWT.NONE);
		CancelButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				loginShell.close();	
			}
		});
		CancelButton.setBounds(163, 106, 80, 27);
		CancelButton.setText("\u53D6\u6D88");

	}
MainUI:
protected void createContents() {
		shell = new Shell();
		shell.setSize(786,499);
		String userName="";
		try {
			
			resultSet= statement.executeQuery("select userName from users where userAccount='"+account+"'");
			resultSet.next();
			userName=resultSet.getString(1);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		shell.setText("欢迎使用图书管理系统-"+account+"-"+userName+"("+role+")");
		shell.setMaximumSize(786, 500);
		shell.setMinimumSize(786,500);
		if(role.equals("高级管理员")) {
			Button settingBtn=new Button(shell,SWT.None);
			settingBtn.setText("设置");
			settingBtn.setBounds(410,10,80,27);
			settingBtn.addSelectionListener(new SelectionListener() {
				
				@Override
				public void widgetSelected(SelectionEvent arg0) {
					// TODO Auto-generated method stub
					try {					
						resultSet=statement.executeQuery("select * from settings");
						resultSet.next();
						String maxAllowedTotalBorrowCountStr=resultSet.getString(1);
						String maxAllowedSingleBorrowCountStr=resultSet.getString(2);
						//new OperationPanel(account,userName, operationStr,objectStr,tipStr,labelStrArray,defaultValuesArray,editAllowedArray, statement);
						OperationPanel settingOperationPanel=new OperationPanel("","","设置","","请输入以下选项",new String[] {"最大可借数量","单本最大可借数量"},new String[] {maxAllowedTotalBorrowCountStr,maxAllowedSingleBorrowCountStr},new Boolean[] {true,true},statement);
						settingOperationPanel.main(null);
					}catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
				
				@Override
				public void widgetDefaultSelected(SelectionEvent arg0) {
					// TODO Auto-generated method stub
					
				}
			});
		}
		
		update();
		Button updateBtn = new Button(shell, SWT.NONE);
		updateBtn.setBounds(500, 10, 80, 27);
		updateBtn.setText("\u66F4\u65B0");
		updateBtn.addSelectionListener(new SelectionListener() {			
			@Override
			public void widgetSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub
				//expandBar.set
				update();
			}			
			@Override
			public void widgetDefaultSelected(SelectionEvent arg0) {
				// TODO Auto-generated method stub				
			}
		});
		Button BackwardBtn = new Button(shell, SWT.NONE);
		BackwardBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				shell.close();
				LoginShell2 loginShell2=new LoginShell2();
				loginShell2.main(null);
			}
		});
		BackwardBtn.setBounds(590, 10, 80, 27);
		BackwardBtn.setText("\u8FD4\u56DE\u767B\u5F55\u9875\u9762");
		
		Button exitBtn = new Button(shell, SWT.NONE);
		exitBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				shell.close();
			}
		});
		exitBtn.setBounds(680, 10, 80, 27);
		exitBtn.setText("退出");
		
		
	}	
	void update() {		
		if(expandBar!=null)
			expandBar.dispose();
		expandBar=new ExpandBar(shell, 0);
		expandBar.setBounds(10, 38, 750, 425);
		expandBar.addExpandListener(new ExpandListener() {		
			@Override
			public void itemExpanded(ExpandEvent arg0) {
				// TODO Auto-generated method stub
				for(ExpandItem item:expandBar.getItems()) {
					item.setExpanded(false);//这里循环设置其他扩展项关闭
				}
			}			
			@Override
			public void itemCollapsed(ExpandEvent arg0) {
				// TODO Auto-generated method stub 这个不用管
			}
		});
		for(String expandItemStr:itemArray) {			
			String[] tableHeadersStrArray= {};
			String[] operationStrArray= {};
			String tableName="";
			switch (expandItemStr) {
			case "所有书籍":
				try {
					tableName="books";
					if (role.indexOf("管理员")!=-1)
						operationStrArray=new String[] {"添加","删除","修改","查找"};
					else
						operationStrArray=new String[] {"查找"};					
					tableHeadersStrArray=new String[] {"ISBN","书名","作者","类型","出版社","出版日期","馆藏数量","借出数量","未借出数量","状态","添加日期"};
					resultSet=statement.executeQuery("select isbn,bookName,author,bookType,publisher,publishDate,totalCount,borrowedCount,unborrowedCount,bookState,

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

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

相关文章

京东平台上API接口的接入|获取京东工业商品详情数据

京东获得JD商品详情 API 返回值说明 item_get-获得JD商品详情 onebound.jd.item_get 公共参数 请求地址:申请KEY调用测试 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称&#x…

Redis基础——入门数据类型常用命令Java中操作Redis

这里写目录标题 1. 前言1.1 什么是Redis1.2 使用Redis能做什么 2. Redis入门2.1 Redis简介2.2 Redis下载与安装2.2.1 Redis下载2.2.2 Redis安装 2.3 Redis服务启动与停止2.4 Redis配置文件 3. Redis数据类型3.1 介绍3.2 Redis 5种常用数据类型 4. Redis常用命令4.1 字符串strin…

NX二次开发UF_CURVE_create_arc_center_radius 函数介绍

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_create_arc_center_radius Defined in: uf_curve.h int UF_CURVE_create_arc_center_radius(tag_t center, double radius, tag_t help_point, UF_CURVE_limit_p_t limit_p…

LeetCode(34)有效的数独【矩阵】【中等】

目录 1.题目2.答案3.提交结果截图 链接: 36. 有效的数独 1.题目 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗…

iOS蓝牙应用的后台处理,iOS蓝牙弹窗“xxx配件想要打开APP”

CBConnectPeripheralOptionNotifyOnConnectionKey: 在应用挂起后,与指定的peripheral成功建立连接,则发出通知 CBConnectPeripheralOptionNotifyOnDisconnectionKey: 在应用挂起后,如果与指定的peripheral断开连接,则发出通知 CBC…

亚信科技AntDB数据库与库瀚存储方案完成兼容性互认证

近日,亚信科技AntDB数据库与苏州库瀚信息科技有限公司自主研发的RISC-V数据库存储解决方案进行了产品兼容测试。经过双方团队的严格测试,亚信科技AntDB数据库与库瀚数据库存储解决方案完全兼容、运行稳定。除高可用性测试外,双方进一步开展TP…

主播之客户停留与转粉

主播的客户停留可以通过以下方法提升: 1.打造舒适吸引人的直播间,灯光和色彩要重视起来。直播间的灯光作用是根据直播间的大小、色温、角度、照射亮度等,不同的条件都有不同的摆放,而且不同的摆放组合都会带来不同的效果,主播可以根据自己的…

马蹄集第33周

题目一 无重复字串的最长字串 解题思路: 双指针:设置两个指针L,R,分别指向traget的开头和结尾,并且使用一个哈希表存储char到int的映射,然后R,当出现重复的字符,那么要在对应的哈希表里面--。…

借力互联网,民营医院探索互联网医疗服务的发展方向

民营医院互联网医疗服务是指利用互联网技术和平台,为患者提供更加便捷、高效的医疗服务。在当前数字化时代,互联网医疗服务正逐渐成为医疗行业的新趋势,也为民营医院开拓了更广阔的发展空间。下面将围绕这一主题进行讨论: 首先&a…

如何避免光模块接口受到污染?

光模块作为光通信领域一个重要的配件,实现光电和电光的转换,和光纤连接,承载了数据流量的快速转换与传输。因而在整个网络体系中,起着至关重要的作用。虽然光模块在使用过程中,不像交换机和服务器等网络设备一样需要经…

【插件、图表】7种图表漂亮丰富uniCharts(附精选源码32套,涵盖商城团购等)

使用unicharts实现折线图、区域图、柱状图、饼状图、雷达图、环形图、可拖动折线图 <template><view class"content"><view tap"gotoPage(line)" class"list-item"><text>折线图</text></view><view ta…

Lazada测评怎么做?

国内电商行业的发展日趋激烈&#xff0c;卖家想要脱颖而出非常困难&#xff0c;许多卖家选择入驻跨境电商平台开店&#xff0c; 跨境电商平台吸引了许多卖家入驻&#xff0c;而最近有很多朋友在私信问我关于Lazada测评的一些事情 Lazada产品测评流程步骤 怎么测评 这个怎么测…

ZYNQ PL 中断请求

1 中断概念 中断学习 2 ZYNQ 中断框图 上图为 zynq 中断分布框图。可以看到部分 PL 到 PS 部分的中断&#xff0c;经过中断控制分配器&#xff08;ICD&#xff09;&#xff0c; 同时进入 CPU1 和 CPU0。查询下面表格&#xff0c;可以看到 PL 到 PS 部分一共有 20 个中断可以使…

计算机毕业设计|基于SpringBoot+MyBatis框架的电脑商城的设计与实现(订单和AOP)

计算机毕业设计|基于SpringBootMyBatis框架的电脑商城的设计与实现&#xff08;订单和AOP&#xff09; 该项目分析着重于设计和实现基于SpringBootMyBatis框架的电脑商城。首先&#xff0c;通过深入分析项目所需数据&#xff0c;包括用户、商品、商品类别、收藏、订单、购物车…

中科亿海微除法器(DIVIDE)

技术背景 技术概述 FPGA实现除法运算是一个比较复杂的过程&#xff0c;因为硬件逻辑与软件程序的区别。如果其中一个操作数为常数&#xff0c;可以通过简单的移位与求和操作代替&#xff0c;但用硬件逻辑完成两变量间除法运算会占用较多的资源&#xff0c;电路结构复杂&#xf…

文件加密软件哪个好?文件加密软件大盘点

在使用电脑时&#xff0c;我们需要将机密文件、个人隐私等数据存放在电脑中。为了保护文件的安全&#xff0c;我们需要使用文件加密软件来进行保护。那么&#xff0c;文件加密软件哪个好呢&#xff1f;下面我们就来盘点一下。 超级加密3000 超级加密3000是一款专业的数据加密软…

office tool plus工具破解word、visio等软件步骤

第一步&#xff1a;下载工具 破解需要用到office tool plus软件 office tool plus软件下载地址&#xff1a;Office Tool Plus 官方网站 - 一键部署 Office 选择其中一个下载到本地&#xff08;本人选择的是第一个的云图小镇下载方式&#xff09; 第二步&#xff1a;启动工具 …

APP项目的推广方法

APP项目的成功与否与其推广策略密切相关&#xff0c;综合使用这些推广方法&#xff0c;可以帮助APP项目更广泛地被认知&#xff0c;吸引更多的用户&#xff0c;并提高应用在市场中的竞争力。以下是一些常用的APP推广方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公…

echarts 通用线性图

echarts 通用线性图 getLineData() {const myChart echarts.init(this.$refs.chartDom);const option {tooltip: {trigger: axis,},legend: {show: false,textStyle: {fontSize: 14, //字体大小color: #ffffff, //字体颜色},data: [AAA, BBB],},grid: {show: true,left: 10%,…

借助arthas 性能调优全过程

使用 arthas 的trace 命令分析方法耗时瓶颈&#xff1a; 可以看出 bindReloadZoneTimeLimite 耗时最久&#xff0c; 通过分析Bind 底层&#xff0c;将业务粒度进行拆分&#xff0c;加入并发执行 再次使用arthas 追踪单个方法耗时时间&#xff1a; 核心耗时方法&#xff0c…