在写这篇文章之前,首先要感谢我的队友的辛勤付出,没有他们的付出与配合,这个项目是不能顺利完成的。
第一点
经验:项目开始之前应该先向老师或者学长先询问经验、或者到网上查找经验,看看如何开发效率高;一个好的开发工具可以大大提升开发效率
但是我们的做法是:因为我们没有这一块知识,所以想在网上找一份代码来参考一下,但是效果不佳,因为根本不懂这一块的内容,所以看不太懂。于是我们小组第一次开会的时候两个小时除了分工:四个人做四个界面,就只装了一个数据库;
那么我们就需要先找一本好一点的教材入门,我们到图书馆里面寻找这一类的书,但是没有什么收获,后来我们组的S拿出了一份电子版的书供我们参考,但是其实教材的用处不大,我根据这本教材还有一些参考代码写了初始界面,花了我三天左右的时间!(11.18-11.20)然后于11.21,又是我们的队友S,告知了有Window Builder可以像Qt一样可视化开发,因为原来的代码不能移植,于是我就花了一下午的时间重新使用WB设计了一遍,一下午VS三天(这就是效率的差别,浪费了我许多时间,而且收获不大)
第一部分的细节见 这篇博客
写主界面时遇到的主要问题及解决:
- 插入图片大小不能自适应swing组件
解决: 到网上找了在组件中重写图片的算法,新建了common类,将算法封装起来(静态函数) - 没有现成的组件直接实现好友框;
解决:因为窗口体可以分成一个个的小窗个(Panel),于是使用Panel作为容器,按照qq的好友框的样式做了我们的项目的好友框 - 在点击"我的好友“标签时怎么显示所有好友
解决:因为窗格是可以显示和隐藏的、且能重新设置位置,于是在点击我的好友时,重排好友窗格,并设置为显示,再次点击时,设置为隐藏并重拍
通过这个过程我也熟悉了图形界面的设计过程
第二点
经验:在项目开始之前应该先将设计文档写好,包括命名标准,规范;如何实现不同类之间的传参,不同界面传参时要留出什么接口;先确定实现的功能,然后根据功能去设计类的成员变量,需要什么函数(先写出函数名,参数,函数的实现留到具体做的时候),类在设计的时候将功能注释在开头; 还有如何将类打包(结构要规范,查找时有效);对于重要的地方要有注释。
这一点我在写代码的时候就深有体会,虽然我大体上分了几个包:小组件、窗口体、常用函数,但是对于主界面没有将其分为三个窗格,用三个类实现。而是直接用WB写成一个类,所以这一块的参数就直接在initializa函数里面定义了,而不是定义为类的成员,传参时就一直修改,将函数内的变量修改为类的成员,改得有点乱了。同样的窗口之间的传参也是后来通过修改构造函数来传参。虽然能实现功能,但是整体的架构就乱了。体会到了代码结构的重要性
实现主界面功能遇到的主要问题及解决:
- 如查找并添加好友
解决:分为个2步骤
1)数据库中查询是否有此用户的存在:队友S将其Java对数据库的常用操作封装成了一个类,我对其中函数的进行了参数的修改,使其能够被我调用,获取用户的信息。这样我能够在查找窗口查找时判断用户是否存在。
2)确认添加好友后如何更新好友列表:因为主界面无法监听查找窗口的事件,于是我在查找窗口中添加了一个boolean类型的成员sign,作为是否要添加新好友的标志,和添加好友的QQ号,并且将查找窗口变为主界面的一个成员,在点击好友列表的时候添加新的好友,缺点就是需要点击好友标签时才能更新,本来是想主界面的窗格监听鼠标的移动来更新的,但是没有效果。 - 如何移动好友和实现删除操作
解决:对好友窗格设置两个属性:isMember是否是列表成员,isFriend是否是好友,在更新好友栏的函数中先进行判断操作,决定是否删除和移动,再重置好友的窗格
通过这个给过程我也熟悉了数据库的操作
第三点
经验:在项目开始的时候就应该确定好小组中不同部分要怎么连接,要留出什么接口,如何传参,我们这个项目最重要的参数就是QQ号,要通过它查找数据库中的内容,所以这个参数如何传递在一开始就要确定好,还有既然是通信工具,就需要有端口,端口这一参数的传递也很重要,并且,一开始就要确定好端口如何分配
在连接整个项目时遇到的问题及解决:
- 数据库的代码修改,使其能够适应我的主界面的调用
解决:通过询问队友S,和网上查找资料,对数据库类的函数进行了修改,同时修改了我主界面中的更新资料的函数,队友S后来发现了可能有sql注入的风险,写了一个判断的函数,将其加入了数据库类中,点赞 - 如何将主界面和对话窗口合并
解决:
1)在和队友L的讨论中,添加了端口这一参数,并且修改了构造函数来传递端口参数,因为队友L原来的代码中端口是固定的,于是修改了端口的参数,但是发现不行,debug过程中发现双击好友窗格,弹出的客户端"对话窗口"时,传给对话窗口的参数应该是自己的端口。
2)但是用户仍然无法对话,后来靠谱的队友L发现start函数没有运行的问题,于是可以运行了。客户端的问题解决了,然后我写了主函数,判断服务器什么时候应该启动。 - 将登录界面和主界面合并,还有将资料界面和主界面合并
解决:
1)登录界面的合并,因为这一部分只需要传递QQnum这一参数,所以比较容易。我和队友W一起进行了登录界面代码逻辑的完善
2)资料界面的和主界面的合并,我和队友W又一起完成了资料界面的代码逻辑,然后就是修改资料需要在主界面更新,这个和好友列表的更新类似,有一个缺点就是需要双击签名栏才能更新主界面的资料
第四点
经验:
- 每做一次修改优化,不止要导出Jar包(可运行,或不可运行),还需要留下代码,方便以后出了bug可以有前一个版本可以参考和使用。
只导了jar包,没导代码的我~ _ ~ - 若新的代码需要对数据库进行修改,那么最好新建一个数据库(防止已有的数据出错)
- 对于每一个版本都要做一次完全的测试(测试工作很重要!!!),都通过了才进行下一个版本的演化
本着将项目做到完美的想法,我开始了我对工程的修改,于是…:
- 添加了右下角任务栏的小图标,这个改得还行
- 因为我希望我们的工程能有较好的移植性:
1)于是我先导出了Jar包使使运行起来如何,但是运行时没有图片,我上网查找了发现是图片路径的问题,因为我的图片都是使用common类中的函数来生成image对象的(没想到这个做法挺有用),于是将所有图片放在和common同一个包,然后使用URL类的对象获取common.class.getResource(pictureName),再通过Ecilpse的search工具修改一下我原来所有图片的路径从src/data/name.jpg变为了name。然后导出包,运行,成功!
2) 然后就是悲惨的故事了,我希望能够我们的项目能够移植到有mysql数据库的新环境,于是我就在调用数据库的类中添加了一个新建新的数据库和新的表的函数,通过网上查找资料,修改了一下函数,调试后,运行起来是能够建立新的数据库和表的,但是我没有测试是否能够注册和登录,能够打开登录界面就觉得万事大吉了,而且没有保存前一个版本能运行的代码。然后答辩时就只能拿初始版本答辩,都是泪啊!!!
队友L的经验
关于“基于JAVA图形化编程进行socket通信”总结:
一. 界面图形化部分:
-
Builder里面会把所有的按键写到构造函数里面,接收消息会出现问题,所以,至少“发送”按钮及其监听要自己手敲代码,写在构造函数之外。
-
把文本框的可写功能关闭之后,并不能阻止客户端通过函数向其内部写入内容,不需要“开启,写入,再关闭”。
-
JAVA的FlowLayout流式布局类,有时候写好后的界面会以一种奇怪的方法排列,直接用Builder会方便很多。
-
JAVA设计出的图形化界面,如果不设置“窗口大小锁定”,随意改变窗口大小,其上的组件也会变得“随意改变”。
二. socket通信部分:
-
服务器用完要关闭,否则再次打开客户端可能会出现“点击发送而没有反应”的现象,即服务器的关闭,应在主函数结束之前完成。
-
尽量不要进行利用时间的监听,延迟很大。
-
单独服务器,A发给服务器要一个端口,服务器发给B要一个端口,B发给服务器要一个端口,服务器发给A要一个端口,四个端口各不相同。
-
如果不建服务器,单独互为服务器和客户端,则只需要两个端口。
-
单独建服务器,只要有足够的客户端,就能轻易地实现群聊功能,而若是互为服务器和客户端,转变为群聊功能则会很复杂。
-
127.0.0.1,本机保留IP地址。
-
服务器要用公网IP,客户端则不一定需要(服务器如果用局域网IP,则与不同主机的客户端无法接通)。
然后项目截图
1.登录界面(队友W完成)
2.注册界面(队友W完成,进行了业务逻辑判断)
3.主界面(我完成)
界面详细见:这篇博客
演示好友列表的功能
(1)移动
5.游戏(队友S完成)
小图标:
6 .聊天界面(队友L完成)
至此,完成。
1.9
我来更新啦
本次提升了软件的可移植性,只要你的电脑装了MySQL数据库,并且输入正确的账号密码,那么就可以在你的电脑上使用了。
思路是:先获取你本地数据库的账号密码,然后将其存在一个文件database中。在第一次运行时会先连接到你本地的数据库,然后创建一个新的数据库和表格。之后每次运行时读取文件database中的账号密码然后连接本地数据库,进行数据库操作