学习pyqt (二)————信号/槽&主次界面&主次线程编程经验总结

2023-11-08

今天准备总结一下pyqt编写界面的经验,这样以后遇到同样问题就可以查看并且很快回忆起来!

环境搭建

经过一周的研究,我发现使用pyqt编写界面最快的方式还是eric + pycharm

使用eric6pycharm同时打开你正在编写的程序,需要界面编写就在eric6里面完成,需要调试并且找到某个变量的类型时,就在pycharm里面设置断点,然后进行断点调试。

主界面绘制经验

主界面绘制方法:

  • 打开左边Project-Viewer栏里面的Form标签
  • 右键选择New Form...里面的Main Window
  • 在弹出的Qt Design里面进行绘制即可

信号和槽的使用经验

如果想要在python中使用信号和槽函数,需要要求使用的类继承QObjcet。然后使用PyQt5.QtCore.pyqtSignal函数新建一个信号,
比如:

from PyQt5.QtCore import QObject, pyqtSignal

class Foo(QObject):

    # 定义一个无参数的信号'closed'。
    closed = pyqtSignal()

    # 定义一个名叫 'rangeChanged' 的信号,包含两个int类型的参数
    range_changed = pyqtSignal(int, int, name='rangeChanged')

    # This defines a signal called 'valueChanged' that has two overloads,
    # one that takes an integer argument and one that takes a QString
    # argument.  Note that because we use a string to specify the type of
    # the QString argument then this code will run under Python v2 and v3.
    valueChanged = pyqtSignal([int], ['QString'])

定义了信号之后,就可以使用该信号的connect方法连接槽,或者使用emit方法发送信号,比如:

from PyQt5.QtCore import QObject, pyqtSignal

class Foo(QObject):

    # 新建一个无参数的信号
    trigger = pyqtSignal()

    def connect_and_emit_trigger(self):
        # 连接槽。
        self.trigger.connect(self.handle_trigger)

        # 发射信号。
        self.trigger.emit()

    def handle_trigger(self):
        # 打印该槽调用成功的消息。

        print "trigger signal received"

主界面和次级界面编程经验

我实际编写界面程序时的原则是:如果不需要次级窗口,就尽量不用,因为每多一个次级窗口,就代表要多两个.py文件。
但是当界面逻辑很多时,如果不用次级窗口,就会导致主窗口的槽函数非常多,看起来不方便。所以到底是否需要用次级窗口。
还是要根据你自己的习惯选择比较好。这里仅仅介绍如何实现次级窗口

Qt内置次级窗口

Qt内置次级窗口比较简单,只需要直接调用函数即可,比如保存对话框:

saveStrList, classify = QtWidgets.QFileDialog.getSaveFileName(self, '选择保存文件', os.path.join(self.FileDirStr, '检测出的异常类型'), 'text(*.txt)')

还有消息提示对话框:

QtWidgets.QMessageBox.about(self, '关于本软件', '本软件版权属于……')

自定义对话框窗口

这里一定要使用QDialog,因为我发现使用QWidget 就没有关闭按钮,不知道为啥。但是Qdialog继续Qwidget,因此使用它肯定能完成Qwidget的任务。

前两步跟编写主界面没区别,在Forms区域新建Qdialog,命名,然后打开QtDesign,绘制自己需要的控件,然后进行绘制即可.

然后在主界面中需要打开该对话框的位置输入代码:

    theSplitWidget = splitDialog()   #splitDialog是我自定义的一个次级窗口
    theSplitWidget.exec_()

主线程和次线程编程经验

在计算复杂任务的时候,为了保证主界面不失去响应,就必须要使用多线程编程。通常情况下,需要让主线程的界面上出现一些进度条或者状态栏提示,让客户可以观察到复杂任务执行进度,这样才能让客户知道程序仍然在正常运行和执行的进度,决定是否继续运行该复杂任务。

自己实现线程,需要继承PyQt5.QtCore.QThread类(一开始我使用多继承同时继承QObjcet和Thread.threading类,发现有问题,最后想到还不如直接继承Qt自带的线程类)。

这样可以自定义信号,因为主线程和次线程的通信要使用信号和槽函数,因为Qt的信号好槽是可以跨线程的,而子线程不能用于直接刷新界面。
如果直接自己定义信号和槽函数,按照“信号和槽的使用经验”里面讲的方式即可,这里创建的线程直接的通信只涉及基本数据结构,这样就不用在Qt中注册元信息了。

思考一下,如果直接主线程逻辑中新建定义一个线程,这样无法完成通信操作

对于复杂到数据结构的通信,我就只让子线程执行完毕后,将结果通过线程的一个函数getResult返回即可。

详细代码如下:

from PyQt5.QtCore import pyqtSignal,QThread

class theThread(QThread):
    def __init__(self):
        super(theThread, self).__init__()

    def setFun(self,fun):
        self.func = fun

    def setArgs(self,args):
        self.args = args
        self.FileDirStr = args[3]

    def getResult(self):
        return self.res

    def run(self):
        print('starting thread', self.name)
        self.res = self.func(self,self.args[0], self.args[1], self.args[2])
        print('finished thread', self.name)

    progress_changed = pyqtSignal(int, name='progressChanged')
    textBrower_changed = pyqtSignal(str, name='textBrowerChanged')
    status_changed = pyqtSignal(str, name='statusChanged')
    autoCheckBox_changed = pyqtSignal(bool, name='autoCheckBoxChanged')
    HeightLineEdit_changed = pyqtSignal(str, name='HeightLineEditChanged')

这样可以看出,在run函数中调用了该线程在设置setFun时的函数。可以看出,线程调用的需要复杂计算量的函数,最好使用**kw关键字参数。因为在设置参数setArgs函数时必须确定传入的参数的数目,用一个关键字参数就可以解决很多问题。
同时函数中需要传入线程本身self的参数,需要更新界面状态就通过线程本身发射信号,这样主线程中开始该线程时要连接对应信号即可。
必然在主线程中连接信号和槽函数的代码可以这样实现:

def __init__(self, parent=None):
        """
        Constructor

        @param parent reference to the parent widget
        @type QWidget
        """
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.thread = theThread.theThread()
        self.thread.progress_changed.connect(self.progressBar_gen.setValue)      #连接Qt的进度条自带的槽函数
        self.thread.textBrower_changed.connect(self.textBrowser_message.append)  #连接Qt的文本浏览器自带的槽函数
        self.thread.status_changed.connect(self.statusBar.showMessage)           #连接Qt的状态栏自带的槽函数
        self.thread.autoCheckBox_changed.connect(self.checkBox_auto.setChecked)  #连接Qt的选择框自带的槽函数
        self.thread.HeightLineEdit_changed.connect(self.lineEdit_height.setText) #连接Qt的行编辑自带的槽函数
        self.thread.finished.connect(self.threadFinished)                        #使用Qt的`Qthread`自带信号连接自定义的槽函数,后面需要实现threadFinished方法!!

注意:前五个槽连接的是Qt对应控件自带的槽函数,最后一个连接的是自定义槽,所以我后面实现了该槽的内容:

def threadFinished(self):
        try:
            IPReg = '(?<![\.\d])(?:25[0-5]\.|2[0-4]\d\.|[01]?\d\d?\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)(?![\.\d])'
            (patternLog_new, patternLog_old, modeClassDF, ParseDF, AnomalyList, timeMap, resultToShow) = self.thread.getResult()
            self.progressBar_gen.setValue(50)
            IPCompile = src.analysisAnomalyModeResult.getCompile(IPReg)
            result = dict()
            for typei in range(len(modeClassDF)):
                inputDf = modeClassDF[typei]
                inputDf.index = [i for i in range(inputDf.shape[0])]  #重排列Index,否则后面使用时会出错
                test = src.analysisAnomalyModeResult.dealOneAnomalyDF(inputDf,IPCompile)
                result['type'+str(typei)] = test
            self.progressBar_gen.setValue(75)
            fileNameForSaveResult = os.path.join(self.FileDirStr,'异常模式结果')
            src.analysisAnomalyModeResult.saveResult(fileNameForSaveResult,result)
            self.progressBar_gen.setValue(100)
            self.end = time.clock()
            self.statusBar.showMessage('生成异常模式完成!一共花费了%.2f秒' % (self.end-self.start))  # 状态栏提示信息
            #记录时间结果显示模块
            totalTime = self.end - self.start
            parseLogTime = timeMap['parseLogTime'] - self.start
            vectorTime = timeMap['vectorTime'] - timeMap['parseLogTime'] 
            logListTime = timeMap['logListTime'] - timeMap['vectorTime']
            filterTime = timeMap['filterTime'] - timeMap['logListTime']
            distanceTime = timeMap['distanceTime'] - timeMap['filterTime']
            clusterTime = timeMap['clusterTime'] - timeMap['distanceTime']

            self.textBrowser_message.append('\n生成异常模式完成!一共花费了%.2f秒:其中解析日志花费时间%.2f秒,占比%.2f%%;计算日志向量花费时间%.2f秒,占比%.2f%%; \
计算日志列表和日志模式花费时间%.2f秒,占比%.2f%%;异常流量筛选花费时间%.2f秒,占比%.2f%%;计算距离矩阵花费时间%.2f秒,占比%.2f%%;进行层次聚类花费时间%.2f秒,占比%.2f%%。'
            % (totalTime, parseLogTime, parseLogTime/totalTime*100, vectorTime, vectorTime/totalTime*100, logListTime, logListTime/totalTime*100, filterTime, filterTime/totalTime*100, 
            distanceTime, distanceTime/totalTime*100,clusterTime, clusterTime/totalTime*100,))
            QtWidgets.QMessageBox.information(self, '提醒', '生成异常模式完成!')
        except Exception as e:
            print(e)
            print(timeMap)
            self.statusBar.showMessage('生成异常模式失败!')  # 状态栏提示信息
            self.progressBar_gen.setValue(0)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

学习pyqt (二)————信号/槽&主次界面&主次线程编程经验总结 的相关文章

  • 如何在 PySide/PyQt 中制作一个位于屏幕中央的小部件?

    这段代码有效 但我想知道是否有更简单的方法 def center self qr self frameGeometry cp gui QDesktopWidget availableGeometry center qr moveCenter
  • 关于在 Qt 中使用未记录的类

    使用无证文件是否安全QObjectUserData类和QObject setUserData in Qt 相反 你可以看看使用QObject setProperty http doc qt io qt 5 qobject html setP
  • C++:头文件中全局函数的多重定义错误

    该函数是全局的 在头文件中定义 暂时地我想把它留在那里 头文件还构成一个具有内联函数的特定类 其中一个函数调用this全局函数 源文件不包含任何有问题的全局函数 有关错误原因的任何提示吗 如果有人感兴趣的话我可以发布代码 mainwindo
  • 如何在Qt无框窗口中实现QSizeGrip?

    如何使用 Qt 无框窗口实现 QSizeGrip 代码会是什么样的 您只需在布局内窗口的一角添加 QSizeGrip 即可使其保持在该角落 QDialog dialog new QDialog 0 Qt FramelessWindowHin
  • 如何在qt中进行异步文件io?

    我想知道如何在qt中实现异步文件io 这在普通的 qt 中是否可以实现 或者有人需要使用另一个库 例如 libuv 来实现这样的事情 我正在查看 QDataStream 但即使它是一个 流 它也不是非阻塞的 我想一种解决方案是制作一个在内部
  • 如何将 QByteArray 转换为十六进制字符串?

    我有打击QByteArray QByteArray ba ba 0 0x01 ba 1 0x10 ba 2 0x00 ba 3 0x07 我真的不知道如何将此 QByteArray 转换为结果字符串 其中包含 01100007 我将使用 Q
  • 获取 QPushButton 在 2D 数组 QPushButton 上的索引

    我有一个二维数组QPushButton 当用户单击按钮时如何获取按钮的索引 例如当用户单击按钮时a 2 3 它会显示 2 3 该示例如下所示 Qt 4 5 使用对象名称 您可以为按钮指定唯一的对象名称 理想情况下 名称应该是有效的 C 标识
  • 如何为 qmlRegisterSingletonType 实现单例提供程序?

    我想在 QML 中使用 C 类作为 Singleton 实例 并认为我必须使用 qmlRegisterSingletonType 注册它们 此函数需要一个提供已注册 C 类的实例的函数 我在 Windows 上使用最新的 Qt 5 3 1
  • 使用 QTextCursor 选择一段文本

    使用 Qt 框架选择文本片段时遇到问题 例如 如果我有这个文件 没有时间休息 我想选择 ime for r 并从文档中删除这段文本 我应该如何使用 QTextCursor 来做到这一点 这是我的代码 QTextCursor cursor n
  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • 如何使 Python、QT 和 Webkit 在无头服务器上工作?

    我有 Debian Linux 服务器 我用它来做各种事情 我希望它能够完成一些我需要定期完成的网络抓取工作 这段代码可以是在这里找到 http bit ly QeqvzX import sys from PyQt4 QtGui impor
  • 在 QtCreator 中使用 .pro 和 .pri 正确(树)显示 Qt 项目

    是否可以使用项目包含文件 pri 显示不止一个额外级别 例如如果 pro文件包括 pri文件包含两个 pri files pro pri pri pri 在 QtCreator 项目 中显示具有误导性 pro pri pri pri 它根本
  • QMutex 是否需要是静态的,以便此类实例的其他线程调用知道暂停其操作?

    从多个线程调用以下附加函数 我不希望数据重写附加 因为计数器尚未增加 除了当前使用 Append 的线程之外 这是否会挂起所有进入的线程 或者其他线程会继续运行而不追加数据吗 互斥锁是否需要是 静态 的 或者每个实例都知道要暂停操作吗 如果
  • 获取 QListView 中所有可见项目的简单方法

    我正在尝试使用 Qt Framework 开发一个图像库应用程序 应用程序从所选文件夹加载所有图像 并使用 QListView 控件显示这些图像 但现在我想通过仅加载用户可见的图像来减少内存消耗 由于没有直接函数来获取视图中的所有可见项目
  • C++ SQL 查询构建库

    我正在寻找一个提供与 c SelectQueryBuilder 库类似功能的 c 库 http www codeproject com Articles 13419 SelectQueryBuilder Building complex a
  • 如何doxygen注释Qt属性?

    我想将 Doxygen 注释附加到我的 Q PROPERTY 例如 song h class Song public QObject Q OBJECT private Q PROPERTY QString title READ title
  • 如何在 Qt 应用程序中嵌入 Python 解释器?

    有没有一种简单的方法可以将 Python 解释器嵌入到 Qt 应用程序中 如果可能的话 我希望有一个跨平台的解决方案 这就是目的PythonQt http pythonqt sourceforge net 它支持 Windows Linux
  • Qt中Q_PROPERTY的意义是什么?

    我无法理解 Q PROPERTY 的用法 Q PROPERTY 如何帮助程序具有防御性 它是干什么用的 我看过这个论坛 但确实无法应用 我已经理解了这个例子 但不明白它的用法 这是一个例子 我能从中得到什么 我知道阅读将赋予只读特权 wri
  • 如何在Android中使用QML - QWebView

    我想在 Android 中部署一个 YouTube 应用程序 但它只能在我的电脑上运行 在安卓上不起作用 它不加载任何视频 问题仅出在 QWebView 上 我使用了与此类似的代码 http doc qt io archives qt 5
  • PyQt4 信号和槽

    我正在使用 PyQt4 编写我的第一个 Python 应用程序 我有一个 MainWindow 和一个 Dialog 类 它是 MainWindow 类的一部分 self loginDialog LoginDialog 我使用插槽和信号 这

随机推荐

  • js 数组过滤操作 过滤两组数组相同的 id

    过滤两组数组相同的 id const arr1 id 145 firstname dave lastname jones id 135 firstname mike lastname williams id 148 firstname bo
  • Zookeeper 的下载安装

    文章目录 一 下载 二 解压 1 在解压后的 bin 目录下 新增两个文件夹 2 在 conf 下 将 zoo sample cfg 复制一份 重命名为 zoo cfg 3 修改 zoo cfg 三 测试 1 启动服务端 2 启动客户端 3
  • Git下载和Git常用命令

    下载git 要下载和安装 Git 请按照以下步骤进行操作 1 访问官方网站 打开 Git 官方网站 https git scm com 2 下载 Git 安装程序 3 选择适用于你的操作系统的下载链接 Git 支持多个操作系统 包括 Win
  • SpringFramework核心技术一(IOC:基于Java的容器配置)

    Bean和 Configuration Spring新的Java配置支持中的中心构件是 Configuration注释类和 Bean注释方法 一 基本概念 Bean和 Configuration Spring新的Java配置支持中的中心构件
  • Nginx下同域部署多个Vue项目(history路由模式),报404、500错误

    主要内容 一 环境 二 问题描述 三 问题解决 1 修改vue项目中的vue config js文件 2 修改Nginx的nginx conf配置文件 3 Nginx目录结构 一 环境 系统 windows nginx 1 20 2 nod
  • 整理 qt opengl,自己的基础框架 —— 绘制一个彩色三角形

    网上很多都是QGLWidget例子 而cube 虽然说明文档上说再简单不过了 但是对于一个0基础的来说 还是像看天书一样 opengl的例子还有一个hellgl2 看着比较简单 但是那个log生成的代码使用了QVector3D显得有点复杂
  • laravel 操作mysql数据库的三种方式

    一 使用DB门面操作 需要引入 DB类 Illuminate Support Facades DB 查询数据库记录 DB select SQL语句 DB select select from stu from 以数组形式返回结果 增加数据库
  • 使整个网页变黑白色(灰色)的特效代码

    全站CSS代码 html filter progid DXImageTransform Microsoft BasicImage grayscale 1 使用方法 这段代码可以变网页为黑白 将代码加到CSS最顶端就可以实现素装 建议全国站长
  • 到现在才理解高斯分布的均值与方差为什么是0和1

    问题的来源 如图所示 为什么标准正态分布的期望值0 方差为1呢 如果是针对x变量 期望值为0可以理解 那么方差为1怎么理解呢 显然不可能为1 如果针对y变量 显然所有值都大于0 怎么会期望值会大于0呢 先看数学期望的定义 期望值本身是对所有
  • 网络性能评估

    在Linux中常见的网络性能指标如下 l 带宽 表示链路的最大传输速率 单位是b s 比特 秒 在位服务器选网卡时 带宽就是最核心的参考指标 常用的带宽有1000M 10G 40G 100G等 网络带宽测试 测试的不是带宽 而是网络吞吐量
  • pycharm激活(JetBrains IDEA 系列产品通用xx方法(license server))

    http xclient info a f0b9738a 36fd 8a97 a966 0d3db497092d html 1 打开激活窗口 2 选择 Activate new license with License server 用li
  • es6 对象的解构用法

    const forms username 王五 password paassword gender 0 result token 1212dsfdasdasdfadasdasdasd id ididididiidid const usern
  • Unity StrangeIOC傻瓜式使用教程(dispatch用法)

    公司用的框架是StrangeIOC 开始完全不知道怎么用 打断点也跟踪不到代码 后来网上各种寻找详解 但是说的都过于高大上 全是专业名词 依赖注入等 完全不适合我这种新人小白理解 最后在自己的各种实践下 总算摸透了其中dispatch用法
  • all query identities do not appear in gallery

    问题描述 在reid strong baslline使用Market 1501数据集训练reid模型后 使用自己的数据集仿照Market 1501制作相同格式的数据集 训练时报如下错误 查看原因 Martet 1501中Query和gall
  • python中安装完virtualenv,创建虚拟环境时报错'virtualenv' 不是内部或外部命令,也不是可运行的程序

    创建虚拟环境包时会报 virtualenv 不是内部或外部命令 也不是可运行的程序 错误 首先排除是否是单词拼写错误 在网上查了好久都没有自己出现的那种情况 可以成功安装 通过pip list 查询时显示安装成功 但会有两行黄色字 大致意思
  • gradle各版本下载地址

    http blog csdn net wangqjpp article details 52218314 gradle各版本下载地址 http services gradle org distributions 以前都是手动下载gradle
  • C语言的整型溢出问题

    整型溢出有点老生常谈了 bla bla bla 但似乎没有引起多少人的重视 整型溢出会有可能导致缓冲区溢出 缓冲区溢出会导致各种黑客攻击 比如最近OpenSSL的heartbleed事件 就是一个buffer overread的事件 在这里
  • wx.getUserProfile使用方法

    1 单独使用 wx getUserProfile desc 展示用户信息 声明获取用户个人信息后的用途 后续会展示在弹窗中 请谨慎填写 success res gt console log res this setData userInfo
  • SymPy Tutorial(译)

    小记 2020 2 26 本文是翻译 官方SymPy手册指南 只是为了方便而自己翻译 前言 本教程假设读者已经了解Python编程语言的基础知识 如果您还没有掌握 建议学习官方的Python教程 本教程假设您具有良好的数学背景 大多数例子需
  • 学习pyqt (二)————信号/槽&主次界面&主次线程编程经验总结

    今天准备总结一下pyqt编写界面的经验 这样以后遇到同样问题就可以查看并且很快回忆起来 环境搭建 经过一周的研究 我发现使用pyqt编写界面最快的方式还是eric pycharm 使用eric6和pycharm同时打开你正在编写的程序 需要