The use of Python and PyQt5 (2)

After designing the components we need through QT Designer, the following is the use of the code!

1. Create a new main file to realize various functions of QT

After the UI file is converted into a Py file through PY UIC, a logic function Py file with the following code will be generated

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", "选择"))

However, in order to separate the UI design file from the logic function file, a new py file is usually created and imported into the Ui_MainWindow in the newly generated GUI.py.

这里定义的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 Set the size, title and icon of the window

The window object is instantiated through mywindow(), and the window represents our main window, and the window can be operated through the window object.

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_())

Or implement it in the created main window class, self is equivalent to the object.

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

insert image description here

1.2 QT interface initialization display picture

Usually we connect the button key trigger with the slot function. In fact, it is to .setPixmapdirectly .

        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'))

insert image description here

So when the code runs here, the interface will have an initialization interface.

1.3 Close the window

Drag the push button in QT Designer and change the text to "Close",
insert image description here

Here self.pushButton, pushButton is the objectname of the above component.
It is to connect the click event triggered by pushButton with the close_window slot function

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 Select and read the files in the folder

// 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)

Here I select a picture file under a folder, and print out the picture path address.
insert image description here

1.5opencv reads local folder pictures and QLabel displays pictures

insert image description here

Here we connect the push_button component "Select" with the open folder, after obtaining the image path, use Opencv to read in the image, and generate QImae image data, and finally display it in QLabel.

Here QImage.Format_RGB888, because the picture is a 24-bit RGB picture, it can be modified as needed

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))

insert image description here
insert image description here

1.6 The main interface displays the current computer time

Mainly, it needs to be realized through QTimer(), QDate, : create a timer, and after the set timing time is up, generate a signal and connect it with the slot function , and get the date and time of the current system at the same time, and finally get the date and time , converted into characters, displayed in QLabelQTime
QTimer()
QDateQTime .currentDate

    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())

insert image description here

1.7 Creation of the menu bar

There are mainly two methods:
(1) Combined with QT Designer,
double-click "Type Here", enter "File(&F)" and press the Enter key. (&F) means to open directly through the "Alt + F" shortcut key.
insert image description here
insert image description here
Next, in the current menu item, create a second-level menu,
insert image description here
double-click to enter your own content, and press Enter.
insert image description here
Finally, the corresponding function is realized by connecting with the slot function:
in the operation of the menu bar, pay attention to the connection of the slot function triggered.connect. .
actionopen is the objectName of this menu item. Here I use the default (can be modified as needed).

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

(2) Code generation

    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)')

insert image description here
After the menu bar is created, a secondary menu is created under the corresponding menu item.
In fact, QAction creates a specific action, and then connects this action with the slot function.
Finally, .addActionselect which first-level menu item the action of this second-level menu will be added to.

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

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

insert image description here
Let me introduce the setting of the shortcut key again:
after creating the QAction action, you can .setShortcutcreate .

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

This means that the QAction action is realized through the "ctrl + o" shortcut key.

1.8 Create a sub-interface

In fact, it is not difficult. If you need to add some functional requirements to the sub-interface, in fact, each interface is independent. Finally, after opening the corresponding sub-interface through the slot function connection, it is equivalent to operating the sub-interface you set in the sub-interface. These functions are gone!
Here we combine the above menu bar and use the open sub-interface in the menu bar.
First create a new Widget window, after generating the .UI file, PY UIC generates the logic file .py.
insert image description here
We are still the same as the main window above, in order to separate the UI design file from the logic function file, we usually create a new py file.
#Here is actually the same as the main window inheritance, because it is the created QWidget window, so the newly created py file here inherits the QWidget in QtWidgets, and the py logic function file of the QWidget window generated by QT

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)

The next step is to open the sub-interface of the menu bar in the main window
. Instantiate the sub-interface in the main window, and then connect the QAction action of the menu item with the slot function for opening the sub-interface.

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()

insert image description here
Then some routine operations in the sub-interface: setting the window size, title, icon... are the same as the main window method detailed above. .

2. QT combined with camera to read, display and save

In order to facilitate the calling of various functions of the camera, a camera class is created here, which encapsulates the methods we need to use: open the camera
, read the camera data, convert the read camera data into a QImage format that can be displayed by QT, and close the camera

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 display camera screen

The biggest problem here is that when QT displays the camera picture, it cannot achieve a very smooth real-time shooting picture.
Here and the above QT show the same reason for the current system. You need to create a timer, then start to get the system time/date timer,
set how often to generate a signal, and then connect with the slot function.
Here it is connected with the show_cameradata slot function, calls the method of reading the screen of the camera class created above, and converts it into QT data format QImage, and displays it in 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 Save the current frame camera screen displayed by QT

The problem encountered here is that when confirming the capture screen, an error occurred when the camera was directly turned off, or after the current frame was saved, the current frame could not be displayed in the QLabel, and the new screen continued to be captured: the timer was not closed
原因. , constantly sending signals, turning off the timer, and then turning off the camera, the current frame can be captured and displayed in the Qlabel.
cv2.imwriteMethod to save the screen to the local

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)

insert image description here
Saved successfully!
insert image description here

Guess you like

Origin blog.csdn.net/weixin_50557558/article/details/130618102