Python和PyQt5的使用(二)

在通过QT Designer设计好我们需要的组件后,下面就是代码的使用啦!

1、新建main文件实现QT的各种功能

通过PY UIC将UI文件转换成Py文件后,会生成如下代码的逻辑功能Py文件

from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(50, 50, 75, 23))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
		#这里往下会显示出你QT Designer设计的组件
        self.pushButton.setText(_translate("MainWindow", "选择"))

但往往为了让UI设计文件与逻辑功能文件分开,通常新建一个py文件,导入刚生成的GUI.py中的 Ui_MainWindow。

这里定义的mywindow类,继承PyQT中的QtWidgets.QMainWindow外,
就是需要继承刚才PY UIC将UI文件转换成Py文件后自动生成的主窗口类Ui_MainWindow
import sys
import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
 
from GUI import Ui_MainWindow  # 导入创建的GUI类

#这里定义的mywindow类,继承PyQT中的QtWidgets.QMainWindow外,
就是需要继承刚才PY UICUI文件转换成Py文件后自动生成的主窗口类Ui_MainWindow
class mywindow(QtWidgets.QMainWindow,Ui_MainWindow):    #这里其实就是主窗口继承QtWidgets中的QMainWindow,还有就是QT生成的主窗口
 
    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = mywindow()
    window.show()
    sys.exit(app.exec_())

1.1设置窗口的尺寸、标题和图标

通过mywindow()实例化window对象,window就代表我们的主窗口了,就可以通过window这个对象对窗口进行操作了。

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = mywindow()
    
    window.resize(700, 500)  # 把显示的主窗口尺寸设置为700 * 500
    window.setWindowTitle('pyqt5--')  # 把显示的主窗口左上角标题命名为pyqt5--
    window.setWindowIcon(QIcon('1.jpg'))  #设置主窗口左上角的图标
    
    window.show()
    sys.exit(app.exec_())

或者在创建的主窗口类中实现,self就相当于对象。

    class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):
        def __init__(self, model_path, dataset_path, filename):
            super(mywindow, self).__init__()
            	self.resize(700, 500)
            	。。。。。
            	。。。。。。

在这里插入图片描述

1.2QT界面初始化显示图片

通常我们是将button键触发和槽函数进行连接。其实,就是将QLabel直接直接通过 .setPixmap直接显示图片。

        def __init__(self, model_path, dataset_path, filename):
            super(mywindow, self).__init__()
            self.setupUi(self)
            self.label.setScaledContents(True)  #将要显示得图片自适应QLabel大小
            self.label.setPixmap(QPixmap('img_1.png'))

在这里插入图片描述

所以这里代码运行时,界面就会有一个初始化界面啦。

1.3关闭窗口

在QT Designer中拖动push button并更改text为“关闭”,
在这里插入图片描述

这里的self.pushButton,pushButton就是上面组件的objectname。
就是将pushButton触发的点击事件与close_window槽函数进行连接

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):  
    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.close_window)
    def close_window(self):
        sys.exit(0)

1.4选择并读取文件夹中文件

// QFileDialog.getOpenFileName()会有返回两个值:
文件地址和文件类型
class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)

        #将 pushButton 的点击事情与槽函数进行连接
        self.pushButton.clicked.connect(self.show_file)

    #打开文件槽函数
    def show_file(self):
        image_path, filetype = QFileDialog.getOpenFileName()
        print(image_path)
        print(filetype)

这里我选择了一个文件夹下的一个图片文件,将图片路径地址打印出来。
在这里插入图片描述

1.5opencv读取本地文件夹图片与QLabel显示图片

在这里插入图片描述

这里我们通过将push_button组件“选择”与打开文件夹进行连接,获取到图片路径后,使用Opencv读入图片,并生成QImae图片数据,最后在QLabel中显示出来。

这里的 QImage.Format_RGB888, 是因为图片是一个24位RGB图片,可以按需修改

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)

        #将 pushButton 的点击事情与槽函数进行连接
        self.pushButton.clicked.connect(self.show_file)

    #QLabel显示图片槽函数
    def show_file(self):
        #获取到文件夹中文件的路径地址
        image_path, filetype = QFileDialog.getOpenFileName()
        img = cv2.imread(image_path)
        image_height, image_width, image_depth = img.shape
        # opencv读出来的是BGR,而在QT中使用正常的RGB显示
        QIm = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        #创建QImage格式,并生成图片
        QIm = QImage(QIm.data, image_width, image_height,
                     image_width * image_depth, QImage.Format_RGB888)
        
        #在QLabel组件中显示QImage图片
        self.label.setScaledContents(True)  #让图片适应QLabel的大小
        self.label.setPixmap(QPixmap.fromImage(QIm))

在这里插入图片描述
在这里插入图片描述

1.6主界面显示当前电脑时间

主要就是需要通过 QTimer()QDateQTime 来实现:
QTimer()创建一个定时器,并且在设置好的定时时间到了后,产生信号并于槽函数进行连接
QDateQTime 同过 .currentDate来获取当前系统的日期和时间
最后将获得的日期和时间,转换成字符,在QLabel中显示

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
        #创建一个定时器
        self.datetime = QTimer()
        # 启动获取系统时间/日期的定时器,定时时间为10ms,10ms产生一次信号
        self.datetime.start(10)
        self.datetime.timeout.connect(self.data_time)
     
     def data_time(self):
        #当前日期
        date = QDate.currentDate()
        self.label_2.setText(date.toString())

        #当前时间
        time = QTime.currentTime()
        self.label_3.setText(time.toString())

在这里插入图片描述

1.7菜单栏的创建

主要是两种方法:
(1)结合QT Designer
双击“Type Here”, 输入“File(&F)”后按回车键。(&F)表示通过“Alt + F”快捷键直接打开。
在这里插入图片描述
在这里插入图片描述
接下来在当前菜单项,创建二级菜单
在这里插入图片描述
双击输入自己的内容,按回车
在这里插入图片描述
最后就是通过与槽函数进行连接,实现对应的功能了:
在菜单栏的操作中,注意槽函数的连接通过triggered.connect来实现。
actionopen就是这个菜单项的objectName。这里我使用默认(可以按需修改)。

    def __init__(self):
        super(mywindow, self).__init__()
        self.actionopen.triggered.connect(self.close_window)

(2)代码生成

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
		menuBar = self.menuBar()  # 实例化一个菜单栏
		# 添加菜单栏中得菜单.......
        fileMenu = menuBar.addMenu('文件(&F)')  
        editMenu = menuBar.addMenu('编辑(&E)')
        formatMenu = menuBar.addMenu('格式(&O)')
        helpMenu = menuBar.addMenu('帮助(&H)')

在这里插入图片描述
菜单栏创建完成后,就是在对应的菜单项下创建二级菜单了。
其实就是,QAction创建一个具体的动作,然后将这个动作与槽函数进行连接。
最后,通过 .addAction选择将这这个二级菜单的动作添加到哪个一级菜单项中。

fileMenu = menuBar.addMenu('文件(&F)')  

aFileNew = QAction('新建(&N)', self)
aFileNew.triggered.connect(self.close_window)
fileMenu.addAction(aFileNew)

在这里插入图片描述
再介绍一下快捷键的设置:
创建好QAction动作后,可以通过 .setShortcut创建快捷键。

aFileOpen.setShortcut(Qt.CTRL + Qt.Key_O)

这个表示通过“ctrl + o”快捷键实现该QAction动作。

1.8创建子界面

其实不难,如果需要在子界面再加一些功能需求,其实各个界面之间都是独立的,最后通过槽函数连接打开对应的子界面后,就相当于在子界面操作你在子界面设置的这些功能了!
这里我们将上面的菜单栏联合起来,使用菜单栏中的打开子界面。
首先新建一个Widget窗口,生成.UI文件后,PY UIC生成逻辑文件.py。
在这里插入图片描述
我们依旧和上面主窗口一样,为了让UI设计文件与逻辑功能文件分开,通常新建一个py文件。
#这里其实就是主窗口继承那里类似,因为是创建的QWidget窗口,所以这里自己新建的py文件继承QtWidgets中的QWidget,还有就是QT生成的QWidget窗口的py逻辑功能文件

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QDockWidget, QListWidget
from PyQt5.QtGui import *
from second import Ui_Form  # 导入子UI界面
class secondwindow(QtWidgets.QWidget, Ui_Form):  # 创建子UI类
    def __init__(self):
        super(secondwindow, self).__init__()
        self.setupUi(self)

接着就是在主窗口中的菜单栏的打开子界面
在主窗口中实例化子界面,再通过将菜单项的QAction动作与打开子界面的槽函数连接。

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):  # 这里其实就是主窗口继承QtWidgets中的QMainWindow,还有就是QT生成的主窗口

    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
        #实例化子界面
        self.second_window = secondwindow()
        self.actionopen_o.triggered.connect(self.open_second)

    def open_second(self):
        self.second_window.show()

在这里插入图片描述
然后在子界面的一些常规操作:设置窗口大小、标题、图标…都和上面详细讲的主窗口方法一样。。

2、QT结合摄像头读取、显示、保存

为了方便对摄像头的各个功能的调用,这里创建一个相机类,里面封装了我们需要用的方法:
打开摄像头、读取摄像头数据、将读取的摄像头数据转换成QT可以显示的QImage格式、关闭摄像头

class camera():
    def __init__(self):
        #self.capture表示打开摄像头的对象
        self.capture = cv2.VideoCapture(0)
        if self.capture.isOpened():
            print("isopenned")
    
    # 读取摄像头数据
    def read_camera(self):
        ret, pic_data = self.capture.read()
        pic_data = cv2.flip(pic_data, 1)  # 摄像头是和人对立的,将图像左右调换回来正常显示。
        if not ret:
            print("获取摄像头数据失败")
            return None
        return pic_data

    # 把数据转换成QT界面能显示的数据格式
    def camera_to_pic(self):
        pic = self.read_camera()
        # 摄像头是BGR方式存储,需要转换成RGB
        self.currentframe = cv2.cvtColor(pic, cv2.COLOR_BGR2RGB)
        # 设置宽高
        #self.currentframe = cv2.cvtColor(self.currentframe, (640, 480))

        # 转换为界面能够显示的格式
        # 获取画面的宽度与高度
        height, width = self.currentframe.shape[:2]
        # 先转换为QImage类型图片(画面),创建QImage类对象,使用摄像头画面数据
        # QImage(data,width,height,format)创建:数据,宽度,高度,格式
        qimg = QImage(self.currentframe, width, height, QImage.Format_RGB888)
        qpixmap = QPixmap.fromImage(qimg)
        return qpixmap

    # 摄像头关闭
    def close_camera(self):
        self.capture.release()

2.1QT显示摄像头画面

这里最大的问题就是QT显示摄像头画面的时候,不能达到一个很流畅的实时拍摄画面。
这里和上面的QT显示当前系统一个道理,需要创建一个定时器,然后启动获取系统时间/日期定时器,
设置好多长时间产生一次信号,然后与槽函数进行连接。
这里就与show_cameradata槽函数连接,调用上面创建好的摄像机类的读取画面的方法,并转成QT数据格式QImage,并在QLabel中显示出来。

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):  # 这里其实就是主窗口继承QtWidgets中的QMainWindow,还有就是QT生成的主窗口
    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
        self.pushButton.clicked.connect(self.open_photo)
        
    def open_photo(self):
        # 实例化一个摄像头
        self.cameravideo = camera()

        #创建定时器
        self.timeshow = QTimer()
        self.timeshow.start(10)
        self.timeshow.timeout.connect(self.show_cameradata)
    
    def show_cameradata(self):
        pic = self.cameravideo.camera_to_pic()
        self.label.setPixmap(QPixmap(pic))

2.2保存QT显示的当前帧摄像头画面

这里遇到的问题就是在确认采集画面时,直接关闭摄像头发生了错误,又或者是保存了当前帧后,当前帧不能够在QLabel中显示,又继续捕获新的画面:
原因就在于定时器没有关闭,不断地在发送信号,关闭定时器,再关闭摄像头,就可以捕获当前帧画面并显示在Qlabel中了。
cv2.imwrite方法保存画面到本地

class mywindow(QtWidgets.QMainWindow, Ui_MainWindow):  # 这里其实就是主窗口继承QtWidgets中的QMainWindow,还有就是QT生成的主窗口
    def __init__(self):
        super(mywindow, self).__init__()
        self.setupUi(self)
        self.pushButton_2.clicked.connect(self.save_img)
    
	def save_img(self):
        pic_data = self.cameravideo.read_camera()
        image_height, image_width, image_depth = pic_data.shape
        QIm = cv2.cvtColor(pic_data, cv2.COLOR_BGR2RGB)
        QIm = QImage(QIm.data, image_width, image_height,  # 创建QImage格式的图像,并读入图像信息
                     image_width * image_depth,
                     QImage.Format_RGB888)
        self.label.setScaledContents(True)  # 将图片在QT界面中显示完全
        self.label.setPixmap(QPixmap.fromImage(QIm))
        # 关闭定时器
        self.timeshow.stop()
        # 关闭摄像头
        self.cameravideo.close_camera()

        self.name = self.lineEdit.text()  #.text()方法获得lineEdit组件的输入内容
      
        os_path = 'D:\\QT\\' + str(self.name)
        os.mkdir(os_path)  # 根据用户名字创建好对应名字的文件夹后,接下来就是将对应名字的文
        # 图片保存下来
        img_path = os_path + '\\' + str(self.name) + '.jpg'
        print(img_path)
        cv2.imwrite(str(img_path), pic_data)

在这里插入图片描述
保存成功!
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_50557558/article/details/130618102