“重构”这个概念来自于SmallTalk(也是一门非常经典的编程语言),很快地就被其他语言圈子的开发者引入到自己的阵营中。
由于在项目开发过程中,重构是其必不可少的一部分,所以当开发人员讨论自己的工作的时候,就诞生了“重构”这个术语。
请点击右上角“关注”按钮关注我们哟:跟着木辛老师学习Python编程知识,变身快乐的编程达人吧~
大家好啊,通过之前的课程,我们学习了如何使用PyQt编写慕课软件的登录和注册页面,也学习了如何使用QSS美化界面样式。
但是,大家有没有发现一个问题呢?
咱们的登录和注册页面有很多部分是相同的,如果今后需要修改这部分内容,咱们需要修改登录和注册两处逻辑。
随着我们开发的进行,如果后续有更多重复的内容,需要修改,我们的多余的工作量将会剧增,这怎么办呢?
修改重复的代码逻辑,容易让人崩溃
今天啊,木辛老师将带领着大家尝试对登录和注册页面进行重构。
重构的概念
什么是重构呢?
“重构”这个概念来自于SmallTalk(也是一门非常经典的编程语言),很快地就被其他语言圈子的开发者引入到自己的阵营中。
由于在项目开发过程中,重构是其必不可少的一部分,所以当开发人员讨论自己的工作的时候,就诞生了“重构”这个术语。
也就是说,所谓重构,就是通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。在不改变其外在行为的前提下,对代码做出修改。
但是,大家一定要注意一点:重构一定要等到代码编程完成之后进行哟!
开始重构
接下来,我们着手对登录和注册页面进行重构了!
分析页面结构
登录页面
登录页面分析
注册页面
注册页面分析
通过如上两个图,可以看出,这两个页面的共同的部分包含
- 左侧部分,背景图和logo
- 右侧部分,顶部软件的名称
- 右侧部分,关闭按钮和最小化按钮
不同部分
- 右侧部分的输入框不同
- 身份选择列表不同
- 按钮不同
- “用户协议”和注册页面跳转不同
思路分析
我们分析一下重构思路
首先,我们需要将相同部分提取出来,然后将不同部分单独出来。
其次,相同部分需要能加载不同部分
再次,将相同部分做成一个父容器,分别调用不同页面的差别部分
最后,需要将事件做重构
既然提到了需要一个父容器可以调用不同的组件,那么就需要一个机制可以实现通过一个公共的窗口加载其他子窗口的逻辑,PyQt中是否存在这样的机制呢?让我们来探索一下。
经过对PyQt文档的苦苦探寻,我们还真找到了一种接近的解决方案:使用一个窗口去加载另一个窗口。
加载其他窗口
根据官方文档的解释,我们尝试先做一个小例子来预演一下可行性吧。
木辛老师说
在软件开发过程中,预演这个过程是必不可少的,是需要通过小样本实验,验证我们的理论是否可行,进而预估开发成本和成功率;另一方面也可以通过预演的demo,给项目负责人展示一个近似的功能逻辑,进而帮助他优化产品模型。
首先,需要打开Qt Designer工具,新建一个窗口,咱们命名为PreviewMainWindow.ui。
将layouts中的Grid Layout拖拽到主窗口中,并适当的调整大小,将其命名为:layout_container。因为我们这个是一个演示,所以就先不做美化了,只要能显示出效果就可以了。
新建父容器
在主窗口上增加一个按钮,用来动态加载另外一个子窗口。就叫它:btn_add_sub_Widget。
然后,再通过Qt Designer创建一个Widget,命名为:ChildrenPreviewForm.ui。
并将InputWidgets中的QPlainTextEdit拖拽到这个Widget中,咱们设置一下描述,方便之后查看效果:写入一段文字:我们尝试一下是否可以通过一个窗口加载另外一个窗口吧!
增加子控件
接着,通过PyCharm的插件PyUIC工具将.ui文件转换为.py文件。并针对两个窗口新建逻辑文件。
主窗口PreviewMainWindow.py对应的是PreviewMainWindow.py
子窗口ChildrenPreviewForm.py对应的是CallChildrenPreviewForm.py
最后,可以开始写具体的Python代码实现窗口调用加载子窗口了。通过在主文件中添加如下代码,实例化子窗口
self.child = ChildrenPreviewForm()
并通过为按钮:btn_add_sub_widget添加事件槽,使其可以在点击的时候出发一个槽函数,将子窗口控件添加到父窗口的容器中。
槽函数的代码如下:
子控件加入到父容器中
可以看到,我们通过控件的addWidget方法将子窗口添加到了父容器中。咱们运行一下看看效果。
点击实现效果
嗯,基本满足了我们的需求。
开始实战 —— 登录模块
还是按照刚才的思路,我们新建一个主窗口,作为父容器。
将商定好的公共空间拷贝过来,放到主窗口中:
制作父容器
在右侧交互区,放置一个QWidget控件。调整各个控件的尺寸和位置。
再分别新建两个子控件:SubLoginForm.ui和SubRegisterForm.ui
通过PYCharm的插件PyUIC将.ui文件转换为.py文件。
同样的,需要新建两个对应的逻辑文件:CallSubLoginForm.py和CallSubRegisterForm.py。
还需要对父控件制作一个对应的逻辑文件:CallAuthMainWindow.py。
将之前写好的QSS代码拷贝到对应的页面中;并将之前最小化按钮和关闭按钮的逻辑代码放入到父容器的逻辑代码中。
好了,具体的页面和逻辑文件都已经建立好了,开始具体的编写调用逻辑吧~
大家一定要注意一点,当软件启动的第一时间,我们需要见登录页面首先呈现给用户,如果用户没有账号,才会通过点击“去注册”按钮,跳转到注册页面。
在我们这里,也就是运行程序后,登录页面自动加载到父容器中:
self.login = SubLoginForm()self.layout_container.addWidget(self.login)
咱们运行一下看看效果:
重构后的登录页面
非常完美,已经可以成功将登录子控件加载到父容器中了。而且测试通过。
到目前为止,我们第一阶段的重构工作:重构登录页面完成,经过人工测试,没有发现明显问题!
接下来呢,我们需要重构注册页面了,在这个过程中呢,重构的过程有一点小复杂。
大家有没有注意到呢?
嗯······,我们之前预演的时候,发起信号槽的按钮是在父容器中的;而此时,我们需要点击子容器中的一个按钮“去注册”,然后唤起父容器更换登录控件为注册控件,这应该怎么办呢?
有点小挑战:模块之间的通信
其实,我们仔细的分析一下软件架构,可以看出,问题其实并不复杂:
- 登录模块中“去注册”按钮需要发起信号
- 而这个信号需要发送给父容器,当父容器成功接收到这个信号之后
- 将注册模块作为一个子模块加载进来
经过分析之后,思路就清晰了,我们需要优先解决的问题是如何通过子控件给父容器发送信号,然后通过父容器的槽函数发起替换子控件的操作。
在PyQt5中,这种实现思路可以叫做:多窗口间传递信号。一般情况下是通过子控件发起信号输出,父容器通过自己的槽函数接收到这个信号之后进行下一步的处理。
需要在登录控件的逻辑文件中定义一个信号变量
Signal_gotoRegister = pyqtSignal()
然后,在“去注册”按钮点击之后,发出一个信号。具体代码可以这么写:
注册事件发送信号
经过上节课的学习,大家已经知道了,当点击“去注册”按钮之后,会出发一个信号,对应的槽函数就是go_to_register()。
此时,执行槽函数的代码块:使用Signal_gotoRegister的emit方法将信号发射出去。
相对应的,需要在父容器中增加一个接收信号的槽函数。代码应该这么写,在CallAuthMainWindow.py中:
self.login.Signal_gotoRegister.connect(self.goto_register)
在槽函数goto_register()中,我们先打印出一个提示信息看看是否能正常运行吧:
接收信号的槽函数
执行效果如下图:
执行效果
嗯嗯,非常不错,已经可以顺利的获取到登录控件发出的信号了!
接近尾声
我们现在需要做的就是如何将layout_container中的登录控件移除,将注册控件添加进来。
可以尝试如下代码:
子控件的更换
通过将旧的子控件的父容器设置为None,然后再将新控件放入容器内,完成页面的替换。
我们执行下程序看看效果吧:
执行效果图
嗯嗯!效果一级棒,经过多次测试,没有发现明显问题,本次重构工作顺利完成!
好了!今天的课程咱们就先到这里吧,同学们是不是觉得这节课学到了很多有意思的知识和技能呀!
木辛老师也希望大家能在之后的时间里多多复习这些知识,并勤加练习。
如果有什么问题请随时联系木辛老师哟!
也请大家持续关注木辛老师的课程哟,获取更多编程知识和编程技巧。
木辛老师的最新专栏,通过视频的方式深入浅出的讲解了更多的Python基础知识,也请同学们持续关注哟!牢固的掌握了Python的基础知识,为今后高阶的编程技能的训练做好准备。
快乐编程,快乐成长!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。