【PyQt5 实战项目1】武汉大学建筑知识系统--思路分享2(软件版本1.0.0介绍之打开图片)

1. 简述

接着上一篇对 PyQt5 项目:武汉大学建筑知识系统的总体概述之后,接下来介绍软件的开发流程和我的一些理解,虽然不能让同学们开发出很牛的软件,但是希望能帮助同学们快速的开发一款能够让老师看得上的一款软件(毕竟在结课展示的时候其他组的软件都被老师痛批)。下面将分几篇文章来展示本软件从初代到最终版本的迭代历程!

2. 版本 1.0.0

从接到这个项目后,用了一个星期的空余时间了解了 PyQt5 这个基于 PythonQt 框架,当时我看的是【《PyQt5 快速开发与实战》王硕 孙洋洋 著】这本书。同时也了解了如何在软件 Qt designer(下简称 designer) 里面构建我们的 UI 界面,关于软件 designer 如何下载获取、配置以及使用,同学们可以去 CSDN 或者 B站 搜索学习,目前这方面的内容还是很多的。那么如何把 PyQt5 用起来,去开发一个项目,我看的是屏信佳(B站用户)的一个实践视频。通过这一个星期的学习,我开始开发软件的第一个版本(同学们可以在网上找找版本的命名方法,一开始我也不是很清楚,所以版本号都是随便就升一个等级,可以看到下面图片的版本号只有2位)。

下面给出版本1.0.0的界面和搭建思路:

  1. 作为一款能让用户上传图片并进行预测的软件,大家应该不难想到一个最基本的功能就是要设计一个东西能让用户上传图片吧,那么在 PyQt5 里面是怎么实现呢?很简单,我们的文件是不是都存放在文件资源管理器(磁盘)里面,那么只需要通过一个 pushButton 按钮 + PyQt5PyQt5.QtWidgets.QFileDialog.getOpenFileName 就可以完成,QFileDialog.getOpenFileName 就是 PyQt5 提供给程序员用于打开用户文件资源管理器的一个接口。
    在这里插入图片描述
    说到这里,同学们可能有疑惑了, pushButton 按钮在哪里呢?QFileDialog.getOpenFileName 这个接口又要如何使用呢?那么相信你肯定没有完成前置步骤(学习 PyQt5 这个框架以及了解软件 designer 的使用)!
    下面简单介绍一下,但是还是希望同学们先去了解相关的知识点再来看本次的项目分享(学习框架 PyQt5 可以看书,图书馆有很多这种书籍,网上也有很多教程;而开发软件可以先在软件 designer 里面把左侧提供的控件全部拖出来试一遍、看一遍,这样了解更深,这也是我之前忽略的一点,后续会继续强调这点)!我们打开软件 designer 选择创建窗体 Widget

    在这里插入图片描述

    在左侧可以看到很多控件,一个个拖出来了解一遍,它将是你开发软件时提供解决方法的一个重要步骤!!!

    在这里插入图片描述

    那么上图画红框的就是 pushButton 按钮啦~

    PyQt5 里面最重要的一点就是要知道信号和槽机制了,这是一个控件通过一些操作能够发生反应的东西,简单来说就是:你要 pushButton 按钮点击之后出现别的功能,那么就要用到这个概念。当然不要被这个名词搞懵了,其实在 PyQt5 里面就是一个语句的事情,即(下面我用的是“森林背词”里面的一个例子,因为在“武汉大学建筑知识系统”我是通过另一种方法实现的)。

    方法一:通过 connect 进行功能函数连接

    self.ui.btn_show_answer.clicked.connect(self.showAnswer)
    # self.ui 是我的整个UI对象
    # btn_show_answer 是我的一个按钮名字
    # clicked.connect 表示这个被点击了,同时发出了信号,这个信号开始通过槽机制调用后面的括号里面的函数(自己定义的一个功能函数)
    # self.showAnswer 则是一个方法(功能函数),在“森林背词”里面用于显示答案的
    

    方法二:通过 PyQt5 提供的 pyqtSlot 来进行功能函数连接

    @pyqtSlot()
    def on_btn_show_answer_clicked(self):
    	......
    
    # 在定义一个功能函数前加上 @pyqtSlot()
    # 然后用 def on_按钮名称_clicked(self): 来实现 showAnswer 这个功能
    

    这个方法是 B站屏信佳提到的,主要用于 pushButton 按钮(其它的控件好像也能用,但是我没全部试过,应该是对于 Buttons 里面的按钮都能用),当你不知道怎么给一个函数命名或者纠结函数叫什么名字的时候(选择困难症用户),用这个可以帮助你抛去这些烦恼,你只要知道点击这个按钮就会实现相应的功能就可以了。但是我建议同学们还是用第一种方法!因为当你开发大型项目的时候,可能会跨文件交互(比如一个类调用另一个类——父类、子类),这个时候方法二可能会失效,同时比如你要实现点击用户头像跳转到用户设置界面,这是就只能用方法一了,所以方法二有一定的局限性

    那么知道了一个按钮的使用,怎么打开用户的文件资源管理器呢?使用 QFileDialog.getOpenFileName注意因为我们只要用户上传一张图片来进行识别,所以选这个接口,当然还有可以选多个文件或者选文件夹的接口,同学们可以自行查阅了解。下面是打开文件的代码示例:

    filename, _ = QFileDialog.getOpenFileName(self, '打开文件', QDir.currentPath())
    # filename 和 _ 见下方图片的解释,即 filename 是用户选择的文件绝对路径,_ 是用户可选择的文件类型
    # '打开文件' 是指打开用户文件资源管理器时左上角的名称(见下图左上角)
    # QDir.currentPath() 是指当前程序主文件所在的路径(当前程序所在的文件夹路径)
    

    在这里插入图片描述
    这样我们的用户上传图片的功能就实现啦~

    那么具体的实现代码同学们可以去我们已经开源的代码里面查看(武汉大学建筑知识系统源代码),这里就不再展示具体代码了,只给同学们介绍思路

  2. 接下来是不是就会想到要保存我们用户上传的图片呀,于是我们可以通过 QImageReader 来获取这个图片,再用 read 方法读取图片,最后用 save 方法保存图片,是不是看的有点懵,下面给出对应代码:

    image_reader = QImageReader(filename)
    image_reader.setAutoTransform(True)  # 启用自动旋转
    image = image_reader.read()
    image.save('.\\predict.jpg', "JPG", 100)	# 第一个参数是保存后图片叫什么名字,第二个参数是保存图片的后缀(不一定要和用户上传图片一样的后缀),第三个参数则是要保存图片的质量(数值越高,画质越高)
    

    这时候同学们看懂了吗?filename 就是我们上面第一步打开文件时返回的一个参数哦,即用户上传的图片绝对路径。我们只有知道用户上传的图片在用户电脑的哪个位置,我们才能将用户上传的图片保存下来!这里相信同学们看到上面多了一句启用自动旋转的语句吧,这是因为不加这句话,那么上传的竖屏图片会被保存为横屏图片!这个方法我当时也是试了很多次才发现的。

    来到这里,有没有同学想到一个潜在的 bug 问题呢?看到这里先闭眼想 10 秒,现在有什么问题呢
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    .
    答案揭晓:之前提到 QImageReader 是不是只是读取图片,但是它不会明显的飞出一个弹窗告诉你读取的是否成功,它只会给你返回一个地址!那么如果一个很皮的用户或者粗心的用户不上传图片文件,而是不小心(故意)上传一个 py 文件,那么这是不是会导致后续在预测过程中出现 bug (因为我们预测的时候要读取这张照片,然后用神经网络来预测嘛)!

    所以我们要在用户上传文件之后去判断用户上传的文件是不是图片文件,如果不是,那么我们就要通过反馈告诉用户要上传图片文件吧,那么怎么判断这个文件是不是图片呢?然后又如何告知用户呢?

    答案是用 isNull 方法,其实 QImageReader 是返回一个地址的,当 read 读取失败时,这个地址内容是 null 。那么如何进行提示呢,那就是用消息框,了解了 PyQt5 小伙伴们肯定知道这个东西了,在 PyQt5 中有很多消息框可供我们选择,我采用的是 QMessageBox 中的 information 来实现,综合起来就是:

            if image.isNull():
                QMessageBox.information(self, '打开图片', '不能加载文件%s.\n请打开图片文件!如后缀为.jpg .png的文件。' % filename)
                return
    

    好的,那么如何打开图片以及保存图片讲解到此结束!

    想想还是给同学们一个简单的代码示例吧,我们先创建一个 .py 文件,就叫 ui.py 吧,这个文件是我们的 UI 界面代码,是通过在软件 designer 搭建好界面,然后通过命令 pyuic5 来将 ui 文件转为 py 文件,具体转换可以自行搜索,这里也提供转换命令供同学们参考。

    pyuic5 ui.ui -o ui.py
    # ui.ui 是我的用软件 designer 搭建的 UI 界面文件
    # ui.py 是指将 ui 文件转为一个名叫 ui.py 的 py 文件
    # 注意:如果 ui 文件或者要转换的 py 文件的路径不是当前路径,则需加上相对路径进行转换哦~
    

    创建好 ui.py 后,输入以下代码:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName("Form")
            Form.resize(278, 64)
            self.gridLayout = QtWidgets.QGridLayout(Form)
            self.gridLayout.setObjectName("gridLayout")
            self.btn_openimage = QtWidgets.QPushButton(Form)
            self.btn_openimage.setObjectName("btn_openimage")
            self.gridLayout.addWidget(self.btn_openimage, 0, 0, 1, 1)
    
            self.retranslateUi(Form)
            QtCore.QMetaObject.connectSlotsByName(Form)
    
        def retranslateUi(self, Form):
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate("Form", "Form"))
            self.btn_openimage.setText(_translate("Form", "打开图片"))
    
    

    方法一:(connect 方法)然后再创建一个 py 文件,叫做 main.py,然后输入以下代码:

    import os
    import sys
    
    from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog, QMessageBox
    from PyQt5.QtCore import pyqtSlot, QDir
    from PyQt5.QtGui import QImageReader
    
    from ui import Ui_Form
    
    
    class QmyWidget(QWidget):
        def __init__(self, parent=None):
            super().__init__(parent)  # 调用父类构造函数,创建窗体
            self.ui = Ui_Form()  # 创建UI对象
            self.ui.setupUi(self)  # 构造UI界面
            self.setWindowTitle("武汉大学建筑知识系统")  # 设置程序窗口名称
            self.ui.btn_openimage.clicked.connect(self.openImage)
    
        # 在识别界面打开图片
        def openImage(self):
            filename, _ = QFileDialog.getOpenFileName(self, '打开文件', QDir.currentPath())
            if filename:
                image_reader = QImageReader(filename)
                image_reader.setAutoTransform(True)  # 启用自动旋转
                image = image_reader.read()
    
                if image.isNull():
                    QMessageBox.information(self, '打开图片', '不能加载文件%s.\n请打开图片文件!如后缀为.jpg .png的文件。' % filename)
                    return
    
                filePath = os.getcwd()
                print(f'预测图片已保存({filePath}' + '\\predict.jpg)')
                image.save('.\\predict.jpg', "JPG", 100)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        w = QmyWidget()
        w.show()
        sys.exit(app.exec_())
    
    

    方法二:(pyqtSlot 方法)然后再创建一个 py 文件,叫做 main2.py,然后输入以下代码:

    import os
    import sys
    
    from PyQt5.QtWidgets import QApplication, QWidget, QFileDialog, QMessageBox
    from PyQt5.QtCore import pyqtSlot, QDir
    from PyQt5.QtGui import QImageReader
    
    from ui import Ui_Form
    
    
    class QmyWidget(QWidget):
        def __init__(self, parent=None):
            super().__init__(parent)  # 调用父类构造函数,创建窗体
            self.ui = Ui_Form()  # 创建UI对象
            self.ui.setupUi(self)  # 构造UI界面
            self.setWindowTitle("武汉大学建筑知识系统")  # 设置程序窗口名称
    
        # 在识别界面打开图片
        @pyqtSlot()
        def on_btn_openimage_clicked(self):
            filename, _ = QFileDialog.getOpenFileName(self, '打开文件', QDir.currentPath())
            if filename:
                image_reader = QImageReader(filename)
                image_reader.setAutoTransform(True)  # 启用自动旋转
                image = image_reader.read()
                print(image_reader)
                print(image)
    
                if image.isNull():
                    QMessageBox.information(self, '打开图片', '不能加载文件%s.\n请打开图片文件!如后缀为.jpg .png的文件。' % filename)
                    return
    
                filePath = os.getcwd()
                print(f'预测图片已保存({filePath}' + '\\predict.jpg)')
                image.save('.\\predict.jpg', "JPG", 100)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        w = QmyWidget()
        w.show()
        sys.exit(app.exec_())
    
    

    这时 main.py 所在的文件夹是不是出现了一个名为 predict.jpg 图片咧,这就是你刚刚上传的图片啦~

    你再试试上传别的图片,是不是图片 predict.jpg 也改变了,这样我们之后就可以通过指定路径来读取图片,从而进行预测啦!

3. 预告

下一篇博客将会介绍识别出用户的图片后将要干些什么?显然是显示建筑的相关信息吧,那我们下篇博客见~

上一篇文章传送门:【PyQt5 实战项目1】武汉大学建筑知识系统–思路分享1(总体概述)

下一篇文章传送门:【PyQt5 实战项目1】武汉大学建筑知识系统–思路分享3(软件版本1.0.0介绍之显示预测的建筑信息、图片)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PyQt5Python编程语言的一种GUI库,用于创建桌面应用程序。它是由Riverbank Computing开发的,为开发者提供了丰富的GUI元素和功能,使他们能够轻松地构建各种用户界面。 而PyQt5-sip是PyQt5的一部分,是一个用于生成Python绑定代码的代码生成器。它将C++头文件转换为Python模块,使开发者能够在Python中使用C++框架和库。PyQt5-sip负责将QObject、QEvent等类和对象转换为Python可调用的代码。 PyQt5PyQt5-sip之间的关系可以简单地理解为:PyQt5-sip是PyQt5的一个重要组成部分,它提供了与C++代码的交互能力,使得PyQt5能够与底层的Qt库进行通信。在安装PyQt5时,PyQt5-sip会自动包含在内,因此我们不需要单独安装或管理PyQt5-sip。 对于开发者而言,了解PyQt5PyQt5-sip的版本非常重要。这是因为PyQt5PyQt5-sip的版本必须相互兼容,以确保代码能够正确地运行。如果您使用的PyQt5版本PyQt5-sip不兼容,可能导致一些错误或功能失效。因此,在使用PyQt5时,我们需要确保选择合适的PyQt5-sip版本与之配套。 总结来说,PyQt5是一款强大的GUI库,而PyQt5-sip是PyQt5的重要组成部分,用于生成与C++代码交互的Python绑定代码。了解并选择合适的PyQt5PyQt5-sip版本对于确保顺利开发和运行PyQt5应用程序是必要的。 ### 回答2: PyQt5PyQt5-sip 是两个与 Python 语言结合使用的库。这两个库的版本是相互关联的。 PyQt5 是基于 Qt 库的 Python 封装,可以用于开发图形界面应用程序。它提供了丰富的 GUI 组件和功能,可以通过 Python 代码来创建和控制界面。 PyQt5-sip 是 PyQt5 的依赖库,它是用于处理 Python 对象和 Qt 对象之间的转换和通信的工具。它实际上是 PyQt5 的一部分,负责生成包装 Qt 类的 Python 类的代码。 这两个库的版本是相关的,因为 PyQt5-sip 的版本必须与 PyQt5版本相匹配。如果版本不匹配,可能会导致库之间的不兼容性和错误。因此,在使用 PyQt5 时,你需要根据 PyQt5版本来选择相应的 PyQt5-sip 版本。 通常,你可以通过以下命令来安装最新版本PyQt5PyQt5-sip: ``` pip install PyQt5 ``` 然后,PyQt5-sip 会自动安装为 PyQt5 的依赖项。 总的来说,PyQt5PyQt5-sip 是用于 Python GUI 开发的重要工具。在使用时需要注意版本匹配,以确保两者能够正常工作。 ### 回答3: PyQt5是一个Python绑定的Qt库,它允许开发者通过Python语言来开发跨平台的图形用户界面(GUI)应用程序。 而pyqt5-sip是PyQt5的一个SIP模块,用于将C++库和Python语言进行交互。它是一个必需的依赖项,需要与PyQt5配套使用。 PyQt5-sip是由Riverbank Computing提供的一款工具,它通过SIP(一个Python/C++通信框架)来实现C++和Python的互操作性。SIP工具将C++代码转换成Python代码,使得开发人员可以在Python中直接调用C++代码和库。 在使用PyQt5时,我们需要安装和配置PyQt5pyqt5-sip两个软件包。PyQt5提供了丰富的Qt类和方法,用于创建各种类型的GUI应用程序。而pyqt5-sip则是在PyQt5中作为连接器的角色,它将C++对象转换为Python对象,并使得Python能够直接调用C++代码和库,实现了二者之间的桥梁。 需要注意的是,PyQt5pyqt5-sip的版本需要匹配,才能保证二者的兼容性。因此,在安装PyQt5pyqt5-sip时,应该选择合适的版本,并确保它们能够正确地配合使用。 总的来说,PyQt5是一个功能强大的库,用于开发Python GUI应用程序,而pyqt5-sip是其所依赖的一个模块,用于实现C++和Python之间的互操作性。它们共同工作,帮助我们使用Python语言开发出跨平台的GUI应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值