图像化界面开发之QT入门

       想要完成一个应用程序的开发,通常还需要一个可视化界面,QT就是可以帮助我们快速开发出可视化界面的一款工具,而利用QT实现页面布局,一般有两种方式,即通过qtdesigner和通过纯代码构建,第一种方式简单易见,可以通过拉取模块的方式快速实现页面的布局,而第二种方式需要自己心中首先构建好页面布局再进行编码,根据自己的需求进行选择。安装配置:https://blog.csdn.net/px41834/article/details/79383985

1、认识QtDesigner

       打开QtDesigner,可以看到如下的界面,左侧是控件等,中间是页面的原始画布,右侧是其对应的属性,通过左侧拉取目标控件到画布上,然后在右侧属性中对其进行修改,可以实现界面的初始布局。

图像化界面开发之QT入门_第1张图片

下面对其进行详细介绍,

(1)控件   


布局(layouts)

图像化界面开发之QT入门_第2张图片

布局:

  • 垂直布局
  • 水平布局
  • 网格布局
  • 表格布局

 


空间间隔组(Spacers):

图像化界面开发之QT入门_第3张图片
  • l Horizontal Spacer:水平间隔。
  • l Vertical Spacer:垂直间隔。

 


按钮组(Buttons)中各个按钮的名称依次解释如下:

图像化界面开发之QT入门_第4张图片
  • l Push Button:按钮。
  • l Tool Button:工具按钮。
  • l Radio Button:单选按钮。 
  • l Check Box:复选框。
  • l Command Link Button:命令链接按钮。
  • l Button Box:按钮盒。

 


项目视图组(Item Views):

图像化界面开发之QT入门_第5张图片
  • lList View:清单视图。
  • lTree View:树视图。
  • lTable View:表视图。
  • lColumn View:列视图。

 


项目组控件组(item widgets)

图像化界面开发之QT入门_第6张图片

 


容器组(Containers):

图像化界面开发之QT入门_第7张图片
  • lGroup Box:组框。
  • lScroll Area:滚动区域。
  • l ToolBox:工具箱。
  • l TabWidget:标签小部件。
  • lStacked Widget:堆叠部件。
  • lFrame:帧。
  • lWidget:小部件。
  • lMdiArea:MDI区域。
  • l DockWidget:停靠窗体部件。
  • lQAxWidget:封装Flash的ActiveX控件。

 


输入部件组(Input Widgets):

图像化界面开发之QT入门_第8张图片
  • lCombo Box:组合框。
  • l FontCombo Box:字体组合框。
  • l LineEdit:行编辑。
  • l TextEdit:文本编辑。
  • lPlain Text Edit:纯文本编辑。
  • l SpinBox:数字显示框(自旋盒)。
  • lDouble Spin Box:双自旋盒。
  • l TimeEdit:时间编辑。
  • l DateEdit:日期编辑。
  • lDate/Time Edit:日期/时间编辑。
  • l Dial:拨号。
  • lHorizontal Scroll Bar:横向滚动条。
  • lVertical Scroll Bar:垂直滚动条。
  • lHorizontal Slider:横向滑块。
  • lVertical Slider:垂直滑块。
  • l Keysequence Edit:按键序列编辑。

 


展示控件组(display widgets)

图像化界面开发之QT入门_第9张图片

 


还可以自定义一些控件,这里就不在赘述,详细可参考https://gitee.com/feiyangqingyun

(2)信号与槽

      信号就是页面中的一些操作事件,传递给槽函数进行后续的处理,如点击信号,双击信号等,而槽函数就是对接收到的信号进行相应的函数。在QtDesigner中实现信号与槽,可以通过如下操作

图像化界面开发之QT入门_第10张图片

2、一些小知识点

》信号与槽之间的传参

图像化界面开发之QT入门_第11张图片

具体实例

基于lambda表达式:widget.signal.connect( lambda: slot(para) )
基于[]:widget.signal[par].connect(slot)
基于partial函数:widget.signal.connect( partial(slot,para) )

》多线程

图像化界面开发之QT入门_第12张图片

图像化界面开发之QT入门_第13张图片

实例(实现一个简单的视频播放器):

#!/usr/bin/env python
#-*- coding:utf-8 -*-
# author: albert time: 2020/6/20

import sys
from PyQt5.QtWidgets import  QApplication,QWidget,QPushButton,QLabel,QVBoxLayout,QFrame,QFileDialog
from PyQt5.QtCore import  QThread, pyqtSignal, Qt
from PyQt5.QtGui import QPixmap, QImage
from PyQt5 import QtGui
import cv2,time

class my_form(QWidget):
    def __init__(self):
        super(my_form,self).__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("load_video")
        self.setGeometry(50,50,800,600)

        ###添加控件
        self.bt1=QPushButton("load_video")
        self.lab=QLabel()
        self.lab.setFrameShape(QFrame.StyledPanel)

        ###添加布局
        ly=QVBoxLayout(self)
        ly.addWidget(self.lab)
        ly.addWidget(self.bt1)

        ###添加槽函数
        self.bt1.clicked.connect(self.play_video)

        self.show()

    def play_video(self):
        videoName,videoType= QFileDialog.getOpenFileName(self,
                                    "打开视频",
                                    "",
                                    " *.mp4;;*.avi;;All Files (*)")
        self.th = Thread(videoName,self.lab.width(),self.lab.height())  ###变成类的属性,否则会出现线程错误
        self.th.changePixmap.connect(self.setImage)
        self.th.start()

    def setImage(self, image):  ###这是在label控件上显示图像或视频
        self.lab.setPixmap(QPixmap.fromImage(image))

class Thread(QThread):#采用线程来播放视频
    changePixmap = pyqtSignal(QImage)
    def __init__(self,videoName,width,height):
        super(Thread,self).__init__()
        self.videoName=videoName
        self.width=width
        self.height=height

    def run(self):
        cap = cv2.VideoCapture(self.videoName)
        while (cap.isOpened()==True):
            ret, frame = cap.read()
            if ret:
                rgbImage = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                convertToQtFormat = QImage(rgbImage.data, rgbImage.shape[1], rgbImage.shape[0], QImage.Format_RGB888)#在这里可以对每帧图像进行处理,
                p = convertToQtFormat.scaled(self.width, self.height, Qt.IgnoreAspectRatio)
                self.changePixmap.emit(p)
                time.sleep(0.01) #控制视频播放的速度
            else:
                break

def main():
    app=QApplication(sys.argv)
    window=my_form()
    window.show()
    app.exec_()

if __name__=="__main__":
    main()

3、使用demo

(1)使用qtdesigner设计界面

      通过上面对各控件的介绍,结合自己的需求进行拖拽布局,首先生成目标布局界面的ui文件,然后再利用pycharm里设计好的pyuic进行转换成可识别的py文件,最后再调用生成的布局py文件并显示,具体操作如下:

》ui布局

图像化界面开发之QT入门_第14张图片

》转换布局py文件

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(526, 349)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(370, 120, 51, 31))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(370, 180, 51, 31))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(Form)
        self.pushButton_3.setGeometry(QtCore.QRect(370, 240, 51, 31))
        self.pushButton_3.setObjectName("pushButton_3")
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(160, 50, 241, 20))
        font = QtGui.QFont()
        font.setFamily("宋体")
        font.setPointSize(20)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(80, 100, 261, 191))
        self.label_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.label_2.setLineWidth(1)
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton.setText(_translate("Form", "载入"))
        self.pushButton_2.setText(_translate("Form", "检测"))
        self.pushButton_3.setText(_translate("Form", "保存"))
        self.label.setText(_translate("Form", "基于深度学习安全帽检测"))

》调用并显示

import sys
from PyQt5.QtWidgets import  QApplication,QWidget,QMainWindow
from load_test import Ui_Form
from PyQt5 import QtCore

class my_form(QMainWindow,Ui_Form):
    def __init__(self):
        super(my_form,self).__init__()
        self.setupUi(self)

if __name__=="__main__":
    QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)  ###保证按原来布局正常显示
    app=QApplication(sys.argv)
    t=my_form()
    t.show()
    app.exec_()

(2)窗口跳转:当窗口A调用窗口B的时候,两个窗口不能是同一类型。如把A写成QWidget类型,把窗口B改成Dialog类型,通过触发A上事件,就可以成功调用B。

class A(QWidget):  
  def __init__(self):  
    ...省略...  
    self.btn = QPushButton('跳转按钮')  
  def initUI(self):  
    pass
  
class B(QDialog):  
  def __init__(self):  
    pass
  def initUI(self):  
    pass
   
if __name__ == '__main__':  
  app = QApplication(sys.argv)  
  a = A()  
  b = B()  
  a.show()  
  a.btn.clicked.connect(b.show)  # 注意show,不要写成show()
  app.exec_()

(3)垂直布局和水平布局,槽函数

import sys
from PyQt5.QtWidgets import  QApplication,QWidget,QPushButton,QFrame,QVBoxLayout,QHBoxLayout
from PyQt5.QtGui import  QColor

class my_class(QWidget):
    def __init__(self):
        super(my_class,self).__init__()
        self.initUI()

    def initUI(self):
        ##窗体初始化
        self.setWindowTitle("test3")
        self.color=QColor(0,0,0)
        dk=app.desktop()
        self.setGeometry(dk.width()/2-self.width()/2,50,400,300)

        ##添加控件
        btn1=QPushButton("red")
        btn1.setCheckable(True)
        btn1.clicked[bool].connect(self.setColor)
        btn2=QPushButton("green")
        btn2.setCheckable(True)
        btn2.clicked[bool].connect(self.setColor)
        btn3=QPushButton("blue")
        btn3.setCheckable(True)
        btn3.clicked[bool].connect(self.setColor)
        self.frame=QFrame()
        self.frame.setStyleSheet("QWidget{background-color:%s}"%self.color.name())

        ###控件布局
        vly=QVBoxLayout()
        vly.addWidget(btn1)
        vly.addWidget(btn2)
        vly.addWidget(btn3)

        hly=QHBoxLayout(self)  ###父容器种的声明需要带上self
        hly.addLayout(vly)
        hly.addWidget(self.frame)

        self.show()


    def setColor(self,p):
        b=self.sender()  ###接受信号,槽函数传参
        v=255 if p else 0
        print(p,b.text(),b)
        if b.text() =="red":
            self.color.setRed(v)
        elif b.text() =="blue":
            self.color.setBlue(v)
        elif b.text()=="green":
            self.color.setGreen(v)

        print(self.color.name())
        self.frame.setStyleSheet("QWidget{background-color:%s}"%self.color.name())


if __name__=="__main__":
    app=QApplication(sys.argv)
    t=my_class()
    app.exec_()

4、打包

   一般而言,当我们开发好了应用程序后,应该将其打包再进行发布,这里推荐使用Pyinstaller将其打包成.exe文件,其中pyinstaller使用方法可以参考《使用Pyinstaller转换.py文件为.exe可执行程序》。打包具体过程如下:

pyinstaller.exe -F call_login.py -w

成功的话,然后会在当前目录下生成三个文件,在dist目录下即可发现打包好的exe格式文件,双击即可运行。

 

参考链接:

https://blog.csdn.net/tsvico/article/details/77001750(Qt学习之Qt控件的介绍)

https://www.cnblogs.com/linyfeng/p/11223707.html([ PyQt入门教程 ] Qt Designer工具的使用)

https://blog.csdn.net/shangxiaqiusuo1/article/details/85253264(PyQt5实现多窗口切换的框架)

你可能感兴趣的:(深度学习,科研生活)