PyQt5基础知识大全

PyQT与Opencv结合的案例
Python 小白从零开始 PyQt5 项目实战(8)汇总篇(完整例程)
PyQt:桌面程序设计的饕餮盛宴
快速掌握PyQt5
个人QT学习笔记(部分重点内容)

生成透明ICO

制作.ico透明图标
在线生成透明ICO图标

设置窗口背景

(1)使用QSS设置窗口背景

#设置对象名称
win.setObjectName("MainWindow")
#todo 1 设置窗口背景图片
win.setStyleSheet("#MainWindow{border-image:url(./images/python.jpg);}")
#todo 2 设置窗口背景色
#win.setStyleSheet("#MainWindow{background-color: yellow}")

(2)使用QPalette设置窗口背景
当使用QPalette(调试板)来设置背景图片时,需要考虑背景图片的尺寸
当背景图片的宽度高度大于窗口的宽度高度时,背景图片会平铺整个背景
当背景图片宽度高度小于窗口的宽度高度时,则会加载多个背景图片

palette = QPalette()
palette.setBrush(QPalette.Background, QBrush(QPixmap("./images/python.jpg")))
win.setPalette(palette)

# todo 1 当背景图片的宽度和高度大于窗口的宽度和高度时
# win.resize(460,  255 )
# # todo 2 当背景图片的宽度和高度小于窗口的宽度和高度时
# win.resize(800, 600)

(3)实现PainEvent,使用QPainter绘制背景

    def paintEvent(self, event):
        painter = QPainter(self)
        #todo 1 设置背景颜色
        painter.setBrush(Qt.green)
        painter.drawRect(self.rect())

        # #todo 2 设置背景图片,平铺到整个窗口,随着窗口改变而改变
        # pixmap = QPixmap("./images/screen1.jpg")
        # painter.drawPixmap(self.rect(), pixmap)

PyQt5图形和特效之设置窗口背景(六)

全部事件处理函数

actionEvent changeEvent childEvent closeEvent contextMenuEvent customEvent
dragEnterEvent dragLeaveEvent dragMoveEvent dropEvent enterEvent focusInEvent
focusOutEvent hideEvent inputMethodEvent installEventFilter keyPressEvent keyReleaseEvent
leaveEvent mouseDoubleClickEvent mouseMoveEvent mousePressEvent mouseReleaseEvent moveEvent
nativeEvent paintEvent removeEventFilter resizeEvent showEvent tabletEvent
timerEvent wheelEvent

QSplitter

SetStretchFactor()用于设定可伸缩控件,它的第一个参数指定设置的控件序号,控件序号按插入的先后次序进行编号;第二个参数为大于0的值表示此控件为可伸缩控件。

setOpaqueResize(true); 设定在拖拽分割条时,是否实时更新。若为true,则实时更新;否则在拖拽时显示一条虚线。

QPainterPath

利用QPainterPath绘制简单图形,QPainterPath 类为QPainter类提供了一个存储容器,里面包含了所要绘制的内容的集合及绘制的顺序,如长方形、多边形、曲线等各种任意图形。当需要绘制此预先存储在QPainterPath对象中的内容时,只需调用QPainter类的drawPathQ函数即可。

QPainterPath 对象的当前点自动处在上一部分图形内容的结束点上,若下一部分图形的起点不在此结束点,则需调用moveTo()函数将当前点移动到下一部分图形的起点。

默认的起点在(0,0),在lineTo()之后,会将path的自动起点位置移到lineTo的点。addRect()或者addRoundedRect()之后会自动将起点移到Rect的左上角顶点
PyQt5基础知识大全_第1张图片

  • QPainterPath裁剪图像
from PyQt5 import QtCore, QtGui

if __name__ == '__main__':
    image = QtGui.QImage('input.png')
    output = QtGui.QImage(image.size(), QtGui.QImage.Format_ARGB32)
    output.fill(QtCore.Qt.transparent)
    painter = QtGui.QPainter(output)

    points = [(444, 203), (623, 243), (691, 177), (581, 26), (482, 42)]
    polygon = QtGui.QPolygonF([QtCore.QPointF(*point) for point in points])

    path = QtGui.QPainterPath()
    path.addPolygon(polygon)
    painter.setClipPath(path)
    painter.drawImage(QtCore.QPoint(), image)
    painter.end()
    output.save('out.png')

环形进度条

Python3 PyQt5自定义圆环进度条(带渐变效果)用多线程实现传参数

画圆环

一、是画一个红色的大圆,再到中间画一个黑色(或透明)的小圆。
二、是构造一个圆环的QRegion使用QPainter的setClipRegion()方法使得只有在圆环区域内图形才能显示。

pyqtgraph添加分隔线

PyQt5_pyqtgraph添加分隔线

信号与槽

详解PyQt5信号与槽的几种高级玩法
在GUI编程中,当改变一个控件的状态时,通常需要通知另一个控件,也就是实现了对象之间的通信。在早期的GUI编程中使用的是回调机制,在Qt中则使用一种新机制信号与槽。

  • 信号与槽的两种连接方法:@pyqtSlot() 和 connect()
  • 信号与槽有三种类型:内置信号与槽、装饰器的信号与槽、自定义信号与槽(内置信号和自定义槽函数、自定义信号和内置槽函数)。
  • 信号-槽机制只是指定信号如何连接到槽,信号定义的参数被传递给槽,而额外的参数(用户定义)不能直接传递给槽函数传递自定义参数: lambda 匿名表达式、 functools 的 partial 偏函数。
  • QT 信号-槽连接类型
    1、Qt::DirectConnection(直连方式)(信号与槽函数关系类似于函数调用。同步运行)
    2、Qt::QueuedConnection(排队方式)(此时信号被塞到信号队列里了,信号与槽函数关系类似于消息通信。异步运行)
    3、Qt::AutoConnection(自己主动方式) Qt的默认连接方式,信号的发出和接收这个信号的对象同属一个线程,那个工作方式与直连方式同样。否则工作方式与排队方式同样。
  • QTimer::singleShot这是个静态函数,能够在给定的时间间隔后调用槽,并不是多次触发该槽函数,该槽函数只执行一次。使用此函数非常方便,也不必创建本地qTimer对象。

处理密集型耗时事件的两种方法

1、多线程
2、QApplication.processEvents()

线程

  • PyQt不允许从其主线程外部访问任何类型的对象,这意味着外部线程无法更新、设置任何控件或部件。在PyQt中使用线程的话最好使用用QThread,QThread基于QObject,QObject的好处是享受PyQt的信号槽机制。在QObject中自定义信号,通过信号发射和接收实现与主线程通讯。该方式需要重写QThread类中的run方法

  • quit()函数是用来停止QThread的,但是由于Qt本身是事件循环机制,所以在调用完quit()后,QThread可能还没有完全停止,此时如果执行delete channel,程序就会报错。==在执行quit()后,调用wait()==来等待QThread子线程的结束(即从run()函数的返回),这样就能保证在清除QThread时,其子线程是停止运行的。

  • 线程自然退出,c++类对象的析构函数能得到执行;调用Terminate线程强行退出,c++类对象的析构函数不能得到正常执行,会造成内存泄漏。而且系统也不会释放线程使用的堆栈!

  • 对于正在运行的线程,如果想要退出,QT5提供了封装好的接口:requestInterruption和isInterruptionRequested。不再需要自定义互斥量和bool类型的退出标记。

  • 有时候我们不希望程序运行到结束,我们需要程序提前终止,这时候我们需要提前退出子线程。
    方法:定义一个停止标志flag,重写stop函数。退出线程直接调用stop函数让flag不满足循环条件,退出循环。

  • 默认情况下,run()通过调用exec()启动事件循环,并在线程内部运行一个Qt事件循环。

  • 界面线程是主线程,如果我们在主线程函数里面调用了一个耗时比较久的循环,可能就会造成主界面线程卡死在循环中,从而造成无法操作主界面或者主界面卡顿、卡死。
    所以这种情况下必须使用多线程的方式来解决,即在主界面线程中在启动一个新的子线程,利用该子线程处理比较耗时的操作,然后通过signal-slot机制将子线程的数据反馈到主界面线程中,而且在子线程中不能操作界面。这就是所说的:UI只用来操作UI,子线程只用来处理数据,就是将UI的操作与耗时数据的处理进行分开处理。

  • UI线程还有一个重要的功能是创建和管理窗体和窗体中的各种控件,负责他们的实时刷新,如果UI线程在处理某个消息的时候耗时特别长,那么后续的消息就无法及时响应,看上去的感觉就是“界面卡死”。
    如何避免界面卡死呢?
    1,负责与用户交互的线程(以下简称为UI线程)应该保持顺畅,当UI线程调用的API可能引起阻塞时间超过30毫秒时(比如访问CD-ROM等速度超慢的外设、进行远程调用等等)就应该考虑使用多线程。对UI线程而言实际上就是:1、发出调用,2、立刻返回。
    2,在Windows Form中使用多线程时,除了创建控件的线程以外,绝对不要在任何其他线程里面直接调用控件的成员,如果需要,请使用invoke或者BeginInvoke。

  • 界面假死
    热启动是指在电脑已经加电的情况下,同时按下Ctrl、Alt 和Del 键,此时将重新启动机器。它通常是在电脑运行中出现“死机”,即按任意键都没有反应时使用。冷启动是指电脑从断电到通电的这么一个启动过程。
    用户在使用软件的时候,常常会遇到系统提示“程序未响应”问题,于是系统就进入了假死状态,判断计算机假死的最简单的方法是按键盘上的NumLock键,看是否有反应,如果指示灯有反应则说明是假死,没有则死彻底了。
    PyQt5 多线程相关一些例子
    PyQT——多线程(QThread)
    PyQt5 QThread应用
    PyQt5高级界面控件之QThread(十二)
    总结,Qt的子线程写法

线程暂停和继续

  • 使用自定义互斥量和bool类型的暂停标记
    定义两个互斥量,一个互斥量用于保护暂停标记,另一个用于保护具体操作
    暂停标记的保护可以使用互斥锁简化操作
  • 对外提供暂停、继续、是否暂停三个接口
    暂停接口修改暂停标记变量,内部循环前判断暂停变量值,如果需要暂停,则QWaitCondition的wait接口阻塞线程。
    继续接口修改暂停标记标记,同时使用QWaitCondition的wakeall接口唤醒所有等待的线程。
    是否暂停接口可以让客户端知道当前线程是否处于暂停状态。
  • 暂停后如果想退出线程,必须先继续线程才能退出
    pyqt5线程的启动,暂停,恢复与停止

线程同步

  • 互斥量 :QMutex
  • 互斥锁:QMutexLocker
  • 读写锁 :QReadWriteLock
  • 信号量:QSemaphore
  • 条件等待:QWaitCondition

线程通信

  • 共享内存
  • 信号与槽

进程通信

  • TCP/IP
  • 共享内存
  • QProcess

视图和控件

  • 列表控件QListWidget,树形控件QTreeWidget和表格控件QTableWidget是基于项(item-based)的控件,它们分别与QListWidgetItem,QTreeWidgetItem以及QTableWidgetItem一起使用。在基于项的控件中,数据是存储于项中再由对应的控件添加进去并显示的。
  • 列表视图QListView,树形视图QTreeView和表格视图QTableView是基于模型的(model-based),也就是说有关数据的获取或者存储操作都是跟模型有关。当我们在处理大量数据的时候,采用基于模型的控件可以让程序的处理速度更快,性能更好。
  • QTableView组件和QTableWidget组件的区别如下:由于QTableView组件相对QTableWidget组件来说只是不具备编辑功能,其他功能保持一致,QTableView组件支持与数据库建立映射关系,如果表格无需更新则最好可以使用QTableView组件。
  • QListWidget、QTreeWidget和QTableWidget分别是对QListView、QTreeView和QTableView封装后的简便类,是后三者的子类,前三者比后三者使用起来较为简单,不过后三者可以让程序在性能上更好,处理速度更快。

QFrame

PyQt5 QFrame
可设置框架形状、框架阴影
PyQt5基础知识大全_第2张图片

关于控件

  • QWidget有两个派生类QDialog和QMainWindow,这三个类都可以用来创建窗口。
    QWidget作为基类,自然可以应用在任何场合,但一切都需要自己动手,白手起家,唯一的好处是想怎么干就怎么干。
    QDialog是对话框窗口的基类,可用来执行短期任务,或者与用户进行互动。对话框窗口可以是模态的,也可以是非模态的,没有菜单栏、工具栏、状态栏等。
    QMainWindow类是GUI程序的主窗口类,提供了构建用户应用程序界面的框架,包括MenuBar、ToolBar、StatusBar、DockWidget、CentralWidget等。因为QMainWindow类有自己的布局,不能像前面的例子那样调用窗口的setLayout方法布局,因此也就不能嵌入到其他窗口,只能作为顶层窗口。如果要对QMainWindow类创建的窗口内的部件布局,应该调用中央部件区的setLayout方法。
    PyQt5基础知识大全_第3张图片

  • 窗口中控件的坐标系
    PyQt5基础知识大全_第4张图片

x()——得到窗口左上角在显示屏屏幕上的x坐标;
y()——得到窗口左上角在显示屏屏幕上的y坐标;
pos()——得到窗口左上角在显示屏屏幕上的x和y坐标,类型为QPoint();
frameGeometry().width()——得到窗口的宽度;
frameGeometry().height()——得到窗口的长度;
frameGeometry().x()——即x(),得到窗口左上角在显示屏屏幕上的x坐标;
frameGeometry().y()——即y(),得到窗口左上角在显示屏屏幕上的y坐标;
frameGeometry()——即pos(),得到窗口左上角在显示屏屏幕上的x和y坐标,以及窗口的宽度和长度,类型为QRect();

geometry().x()——得到客户区左上角在显示屏屏幕上的x坐标;
geometry().y()——得到客户区左上角在显示屏屏幕上的y坐标;
geometry()——得到客户区左上角在显示屏屏幕上的x和y坐标,以及客户区的宽度和长度,类型为QRect();
width()——得到客户区的宽度;
height()——得到客户区的长度;
geometry().width()——得到客户区的宽度;
geometry().height()——得到客户区的长度;

子窗口的位置是基于父窗口的坐标体系来确定的,也就是说通过父窗口左上角的坐标点来确定自己的位置,Qt中窗口显示的时候使用的相对坐标,相对于自己的父窗口,将子窗口移动到父窗口的某个位置。
注:通过geometry()和frameGeometry()获取坐标的相关方法需要在窗口调用show()方法之后才能使用,否则获取的将是无用数据

  • 管理布局的函数中有一个addStretch(int) 方法,该方法就是添加一个占位符,而占位符的大小就是其中填入的数字。我们可以看到在示例中先添加了一个大小为1的占位符,然后再添加用于显示图片的QLabel,最后再加了一个大小为1的占位符。这样做的目的就是为了让这个QLabel控件居中。若将添加的第一个占位符(即左边的占位符)大小设为2,那么QLabel就会偏右,因为左边的占位符大小比QLabel右边的占位符大。

  • QCheckBox通过setChecked()方法传入True或者False可以将复选框设为选中或无选中状态;另外一种替代的方法是setCheckState(),传入的参数可以是选中状态Qt.Checked, 无选中状态Qt.Unchecked和半选中状态Qt.PartiallyChecked;

  • QPushButton通过setCheckable(True)方法可以将按钮设置为一个可标记的按钮,那此时该按钮就拥有了标记和非标记两种状态了。可以通过isCheckable()方法来判断该按钮是否是可标记的

  • QApplication、QGuiApplication、QCoreApplication
    一个QApplication实例,其实就是Singleton模式,QApplication的主要职责如下:
    1、使用用户的桌面设置进行初始化,这些设置如palette()、font()、doubleClickInterval(),然后跟踪这些属性的变化,如用户通过某种配置面板修改了全局桌面设置。
    2、处理事件,从窗口系统接收事件并派发到相应的Widget,使用sendEvent()和postEvent()函数可以派发事件。
    3、处理命令行参数,设置内部状态。
    4、定义GUI外观,外观由QStyle对象包装,运行时通过setStyle()函数进行设置。
    5、设置颜色分配规则,对应的函数为setColorSpec()。
    6、本地化字符串,函数为translate()。
    7、提供了一些有用的对象,如desktop()、clipboard()函数。
    8、知道Widget及Window,相应的函数为widgetAt()、topLevelWidgets()、closeAllWindows()。
    9、管理鼠标光标,函数为setOverrideCursor()。
    【QT】QApplication简介

  • QWidget 模态,模态窗口会阻止其他窗口的输入型事件,但是模态窗口的子窗口不会被限制。通过QWidget 的 setWindowModality() 函数设置,有三种类型:
    PyQt5基础知识大全_第5张图片

  • QDialog 模态,QDialog 是 QWidget 的派生类,不同于 QWidget 的默认无模态,QDialog 有三种情况:PyQt5基础知识大全_第6张图片

  • setCheckable(true)为属性,表示可以选中
    setChecked(true)为属性的值,表示已经选中,可设置按钮初始状态
    setPlaceholderText()方法用于在输入框显示浅灰色的提示文本
    setEchoMode(QLineEdit.Password)将普通输入框中的文字变成原点

  • 从字面上看,show()即可以显示非模式也可以显示模式对话框(设置modal值)。当modal=true的时候是否跟exec()就一样了呢?
    经过测试,还是有区别的。
    使用show(),虽然在对话框弹出的时候,程序的其它操作(按钮、窗口切换等)都失效了;但是程序仍然在调用对话框之后,马上返回继续执行后面的代码。这样,你就不会得到窗口的返回值。以这个来看,show()只能算是“半模式”。
    而使用exec(),在调用之后,程序就被锁定在原地。等待窗口的关闭。
    实际上,QDialog的show()函数来自其父类QWidget。而exec()则是自己的。
    我最近特别喜欢继承QWidget类来做弹出窗口,它的好处就是方便、灵活,既可以做为弹出窗口用也可以嵌入另外的页面里(QDialog是不行的)。但问题是,QWidget没有exec()函数。所以想弹出这样模拟出来的模式对话框就不行了。

  • setCentralWidget
    一个Qt主窗口应用程序必须有一个中心窗口部件(Central Widget)。当你采用Qt Designer创建主窗口时,默认情况下,系统已经为你创建了一个中心窗口部件,它是子类化QWidget的。Qt应用程序的主窗口管理着中心窗口部件,它会在合适的时候销毁这个中心窗口部件。每次程序调用setCentralWidget()方法时,先前存在的中心窗口部件将被新的所替换,而且主窗口会销毁原来的部件,无需用户处理。

  • ObjectName主要是用于外界来访问内部的控件成员的,如果外界不需要访问这个成员,则理论上无需设置它的ObjectName。

  • 许多QWidget对象都支持拖拽动作,允许拖拽的控件必须设置QWidget.setDragEnabled()为True。

高级容器控件

  • 选项卡控件(QTabWidget)
  • 堆栈窗口控件(QStackWidget)
  • 停靠控件(QDockWidget)
  • 容纳多文档的窗口(QMdiArea&QMdiSubWindow)
  • 滚动条控件(QScrollBar)
    PyQt5学习笔记(十一)高级容器控件

PyQt 的Designer中调用Assistant助手

下载地址
关于pycharm安装pyqt5的一些坑
新建bin文件夹,复制下面dll到该文件夹下
PyQt5基础知识大全_第7张图片

软件开机自启动

软件写注册表设置开机自启动
开机启动C++实现
python项目实战:实现电脑开机自启动某软件

4个常用的图像类QPixmap、QImage、QPicture、QBitmap

  • QPixmap 的作用是加载并呈现本地图像,而图像的呈现本质上也是通过绘图方式实现的
  • QImage提供了一个与硬件无关的图像表示函数,可以用于图片的像素级访问;
  • QPicture是一个绘图设备类,它继承自QPainter类,可以使用QPainter的begin()函数在QPicture上绘图,使用end()函数结束绘图,使用QPicture的save()函数将QPainter所使用过的绘图指令保存到文件中;
  • QBitmap是一个继承自QPixmap的简单类,它提供了1bit深度的二值图像的类,QBitmap提供的单色图像可以用来制作游标(QCursor)或者笔刷(QBrush)。
    一篇全面的关于Qt对图像数据的操作总结

关于绘图QPainter 和GraphicsView

1、对于图形的绘制,可以使用 QPainter 实现普通二维图形的绘制,绘图要在painEvent() 方法中实现。在QPainter 对象的begin() 与end() 方法间绘图代码。其本质绘制的图形是位图,这种方法更适合于绘制复杂度不高的固定图形,并且不能实现图项的选择、编辑、拖放、修改等交互功能。
2、painEvent() 绘图事件不用手动调用,通过重写父类虚函数之后会自动调用。自Qt4开始,控件就自带双缓冲绘图功能来消除闪烁问题了,所以没有必要再在paintEvent()事件函数中再编写双缓冲代码。
PyQt5基础知识大全_第8张图片
3、对于需要绘制大量的、需要交互的图形,可使用Graphics View绘图架构,它是一种基于图形项(Graphics Item)的模型/视图模式,这种方式可以在一个场景中绘制大量图元项,且每个图元项都是可选择、可交互的。
4、从QT4.2开始引入了Graphics View框架用来取代QT3中的Canvas模块,并作出了改进,Graphics View框架实现了模型-视图结构的图形管理,能对大量图元进行管理,支持碰撞检测,坐标变换和图元组等多种方便的功能。
5、QPainter采用面向过程的描述方式绘图;GraphicsView采用面向对象的描述方式绘图。对于复杂的图像来说,如果图像包含大量的直线、曲线、多边形等图元对象,管理图元对象比管理QPainter的绘制过程语句要容易,并且图元对象更符合面向对象的思想,图形的可复用性更好。
6、一般使用QLabel控件来显示图片。但是,如果要使用很多图片怎么办?难道要实例化很多个QLabel控件来一一显示?那如何管理呢?当然,我们不可能会用QLabel控件来做这样的事,否则会非常麻烦和混乱。PyQt5中的图形视图QGraphicsView可以让我们管理大量的自定义2D图元并与之交互。
7、Painter中setCapStyle()设置笔端样式,setJoinStyle()设置线条连接方式
PyQt5基础知识大全_第9张图片

视口和窗口

  • 视口(viewport)窗口(window)机制目的是为了绘制与绘制设备的大小和分辨率无关的图形。
  • QPainter的默认坐标的原点(0, 0)位于屏幕的左上角,X轴正方向是水平向右,Y轴正方向是竖直向下。我们在使用 QPainter进行绘制时,传给QPainter的是逻辑坐标,然后,Qt的绘图机制会使用坐标变换将逻辑坐标转换成物理坐标后进行绘制。
  • 窗口以视口为映射对象。映射关系是四个顶点一一对应进行映射
  • 绘图设备的物理坐标是基本的坐标系,通过QPainter的平移,旋转等变换可以得到更容易操作的逻辑坐标。而为了实现更方便的坐标,QPainter还提供了视口和窗口坐标系,通过QPainter内部坐标的变换矩阵自动转换为绘图设备的物理坐标系。
  • 窗口与视口是同一个矩形,不管窗口定义的是方的还是长的,最后都会一一映射到对应视口四个顶点上
  • 窗体变化,视口和窗口显示的图形会随着动态适应变化

视口: 物理坐标,可以只选取物理坐标的一个矩形区域用于绘图。视口默认情况下等于绘图设备的整个矩形区。QPainter绘图的范围就是视口的范围,不能超出视口的范围进行绘图
窗口: 逻辑坐标,窗口坐标的中心在矩形中心, Qt绘图时,如果不显式的指定窗口和视口,默认的窗口和视口都是(0,0,widget.width(),widget.height())

关于图表PyQtGraph、Matplotlib、PyQtChart

  • PyQtGraph要比Matplotlib快的多
  • matplotlib画静态图可以,实时用pyqtgraph,小数据量可以用qchart。大数据实时图还是pyqtgraph
  • Matplotlib的目标更多是制作出版质量的图形,而pyqtgraph则用于数据采集和分析应用。
  • Matplotlib(据我所知)并不包含许多pyqtgraph的功能,如图像交互,体绘制,参数树,流程图等。

pyqtgraph官网
PyQtGraph案例
PyQt5基础知识大全_第10张图片

你可能感兴趣的:(qt)