最近开发一个项目,需要用到界面,遇到界面不能实时更新的问题,看到网上很多用槽函数,但是大多都是些button的,并不是我需要的,要么就是整数的,后来自己进行尝试,写了一个自定义的槽函数处理treewidget,特地分享出来。

背景:用QT Designer设计了一个界面,在程序运行中间调用界面,并随着程序的运行会更新treewidget。

问题1:如果在界面Class中写运行程序,那么结果会等到程序运行结束,最后界面出来,但是此时界面上已经是最终结果

解答:因为会等到程序结束才会加入界面mainloop中,执行到最后一句话,界面才会显示,所以解决办法就是将中间需要处理的代码放到线程中,这样就不会妨碍程序往下走了。

问题二:在线程中代码会需要更新界面,但是界面往往卡顿,只有鼠标点cmd窗口,在点回界面时,数据才刷新,不能更好的看到程序运行的结果。

解答:PyQt5中不友好支持子线程中对界面的设置,需要使用槽函数,信号触发的方式来更新界面。

为了更好的演示,这里先介绍一下把界面和代码分离的方法

现在开始自定义槽函数。

先看分离后的函数:

treeview4_test.py

  1. from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
  2. from PyQt5 import QtCore, QtGui, QtWidgets
  3. import treeview4
  4. import treeview_data
  5. import sys
  6.  
  7. class MainCode(QMainWindow, treeview4.Ui_MainWindow):
  8.  
  9. def __init__(self):
  10. QMainWindow.__init__(self)
  11. treeview4.Ui_MainWindow.__init__(self)
  12. self.setupUi(self)
  13. # 设置列宽
  14. self.treeWidget.setColumnWidth(0, 200)
  15.  
  16. _translate = QtCore.QCoreApplication.translate
  17. self.initial_tree_view(_translate)
  18. self.treeWidget.expandAll()
  19.  
  20. def initial_tree_view(self, _translate):
  21. list_objects = []
  22. test1 = treeview_data.DataCollection()
  23. test1.set_module({"Test1": "waiting"})
  24. test1.add_item({"a1": "waiting"})
  25. test1.add_item({"b1": "waiting"})
  26. test1.add_item({"c1": "waiting"})
  27. list_objects.append(test1)
  28.  
  29. test2 = treeview_data.DataCollection()
  30. test2.set_module({"Test2": "waiting"})
  31. test2.add_item({"a2": "waiting"})
  32. test2.add_item({"b2": "waiting"})
  33. test2.add_item({"c2": "waiting"})
  34. test2.add_item({"d2": "waiting"})
  35. list_objects.append(test2)
  36.  
  37. test3 = treeview_data.DataCollection()
  38. test3.set_module({"Test3": "waiting"})
  39. test3.add_item({"a2": "waiting"})
  40. test3.add_item({"b2": "waiting"})
  41. test3.add_item({"c2": "waiting"})
  42. test3.add_item({"d2": "waiting"})
  43. list_objects.append(test3)
  44.  
  45. for object_num, object_module in enumerate(list_objects):
  46. item_0 = QtWidgets.QTreeWidgetItem(self.treeWidget)
  47. brush = QtGui.QBrush(QtGui.QColor(176, 165, 172))
  48. brush.setStyle(QtCore.Qt.SolidPattern)
  49. item_0.setBackground(0, brush)
  50. for module_name, module_result in object_module.module.items():
  51. brush = QtGui.QBrush(QtGui.QColor(0, 255, 0))
  52. brush.setStyle(QtCore.Qt.SolidPattern)
  53. item_0.setBackground(1, brush)
  54. self.treeWidget.topLevelItem(object_num).setText(0, _translate("MainWindow", module_name))
  55. self.treeWidget.topLevelItem(object_num).setText(1, _translate("MainWindow", module_result))
  56. for item_num, item_dic in enumerate(object_module.items):
  57. for item_name, item_result in item_dic.items():
  58. item_1 = QtWidgets.QTreeWidgetItem(item_0)
  59. self.treeWidget.topLevelItem(object_num).child(item_num).setText(0, _translate("MainWindow",
  60. item_name))
  61. self.treeWidget.topLevelItem(object_num).child(item_num).setText(1, _translate("MainWindow",
  62. item_result))
  63.  
  64. if __name__ == "__main__":
  65. app = QApplication(sys.argv)
  66. md = MainCode()
  67. md.show()
  68. app.exec_()
  69. # sys.exit(app.exec_())

然后调用子线程进行刷新:

  1. from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog
  2. from PyQt5 import QtCore, QtGui, QtWidgets
  3. import treeview4
  4. import treeview_data
  5. import sys
  6. import threading
  7. import time
  8.  
  9. class MainCode(QMainWindow, treeview4.Ui_MainWindow):
  10. list_result_update = QtCore.pyqtSignal([int, int, str])
  11.  
  12. def __init__(self):
  13. QMainWindow.__init__(self)
  14. treeview4.Ui_MainWindow.__init__(self)
  15. self.setupUi(self)
  16. # 设置列宽
  17. self.treeWidget.setColumnWidth(0, 200)
  18.  
  19. _translate = QtCore.QCoreApplication.translate
  20. self.initial_tree_view(_translate)
  21. self.treeWidget.expandAll()
  22. # 用列表触发槽函数
  23. self.list_result_update.connect(self.modified_treewidget)
  24. # 线程函数
  25. self.run()
  26.  
  27. def run(self):
  28. th = threading.Thread(target=self.go_update)
  29. th.setDaemon(True)
  30. th.start()
  31.  
  32. def initial_tree_view(self, _translate):
  33. list_objects = []
  34. test1 = treeview_data.DataCollection()
  35. test1.set_module({"Test1": "waiting"})
  36. test1.add_item({"a1": "waiting"})
  37. test1.add_item({"b1": "waiting"})
  38. test1.add_item({"c1": "waiting"})
  39. list_objects.append(test1)
  40.  
  41. test2 = treeview_data.DataCollection()
  42. test2.set_module({"Test2": "waiting"})
  43. test2.add_item({"a2": "waiting"})
  44. test2.add_item({"b2": "waiting"})
  45. test2.add_item({"c2": "waiting"})
  46. test2.add_item({"d2": "waiting"})
  47. list_objects.append(test2)
  48.  
  49. test3 = treeview_data.DataCollection()
  50. test3.set_module({"Test3": "waiting"})
  51. test3.add_item({"a2": "waiting"})
  52. test3.add_item({"b2": "waiting"})
  53. test3.add_item({"c2": "waiting"})
  54. test3.add_item({"d2": "waiting"})
  55. list_objects.append(test3)
  56.  
  57. for object_num, object_module in enumerate(list_objects):
  58. item_0 = QtWidgets.QTreeWidgetItem(self.treeWidget)
  59. brush = QtGui.QBrush(QtGui.QColor(176, 165, 172))
  60. brush.setStyle(QtCore.Qt.SolidPattern)
  61. item_0.setBackground(0, brush)
  62. for module_name, module_result in object_module.module.items():
  63. brush = QtGui.QBrush(QtGui.QColor(0, 255, 0))
  64. brush.setStyle(QtCore.Qt.SolidPattern)
  65. item_0.setBackground(1, brush)
  66. self.treeWidget.topLevelItem(object_num).setText(0, _translate("MainWindow", module_name))
  67. self.treeWidget.topLevelItem(object_num).setText(1, _translate("MainWindow", module_result))
  68. for item_num, item_dic in enumerate(object_module.items):
  69. for item_name, item_result in item_dic.items():
  70. item_1 = QtWidgets.QTreeWidgetItem(item_0)
  71. self.treeWidget.topLevelItem(object_num).child(item_num).setText(0, _translate("MainWindow",
  72. item_name))
  73. self.treeWidget.topLevelItem(object_num).child(item_num).setText(1, _translate("MainWindow",
  74. item_result))
  75.  
  76. def modified_treewidget(self, num_one, num_two, str_one):
  77. _translate = QtCore.QCoreApplication.translate
  78. self.treeWidget.topLevelItem(num_one).child(num_two).setText(1, _translate(
  79. "MainWindow",
  80. str_one))
  81.  
  82. def go_update(self):
  83. time.sleep(1)
  84. # 更新treeview
  85. self.list_result_update.emit(1, 1, "aaaaaaa")
  86.  
  87. if __name__ == "__main__":
  88. app = QApplication(sys.argv)
  89. md = MainCode()
  90. md.show()
  91. app.exec_()
  92. # sys.exit(app.exec_())

现在就完成了自定义槽函数了。

Python基础之用PyQt5界面代码分离以及自定义一个槽函数的更多相关文章

  1. 基于Python接口自动化测试框架+数据与代码分离(进阶篇)附源码

    引言 在上一篇<基于Python接口自动化测试框架(初级篇)附源码>讲过了接口自动化测试框架的搭建,最核心的模块功能就是测试数据库初始化,再来看看之前的框架结构: 可以看出testcase ...

  2. python基础--小数据池,代码块的最详细、深入剖析

    本文转至太白金星 一,id,is,== 在Python中,id是什么?id是内存地址,那就有人问了,什么是内存地址呢? 你只要创建一个数据(对象)那么都会在内存中开辟一个空间,将这个数据临时加在到内存 ...

  3. Python基础库之jieba库的使用(第三方中文词汇函数库)

    各位学python的朋友,是否也曾遇到过这样的问题,举个例子如下: “I am proud of my motherland” 如果我们需要提取中间的单词要走如何做? 自然是调用string中的spl ...

  4. python基础-requests模块、异常处理、Django部署、内置函数、网络编程

     网络编程 urllib的request模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应. 校验返回值,进行接口测试: 编码:把一个Python对象编码转 ...

  5. Python基础总结之第十一天开始【再深入一下函数,重新认识一下】(新手可相互督促)

    感谢最近大家的关注,希望我的学习笔记对大家有帮助!也感谢各位的评论和推荐,请多多指教. 在重新认识函数之前,我们先看两个函数.一个是我们在前面笔记经常用到的print()  :另一个是input() ...

  6. PyQt(Python+Qt)学习随笔:Qt Designer中连接Action和槽函数

    在Designer中试了半天,终于找到了Action添加槽函数的方法,操作步骤: 在Designer右边界面中点击鼠标右键 确保信号/槽编辑被勾选,如图是未勾选的情况:. 勾选后会出现信号和槽的编辑界 ...

  7. python基础===如何优雅的写代码(转自网络)

    本文是Raymond Hettinger在2013年美国PyCon演讲的笔记(视频, 幻灯片). 示例代码和引用的语录都来自Raymond的演讲.这是我按我的理解整理出来的,希望你们理解起来跟我一样顺 ...

  8. python基础知识-8-三元和一行代码(推导式)

    python其他知识目录 1.三元运算(三目运算) 三元运算符就是在赋值变量的时候,可以直接加判断,然后赋值格式:[on_true] if [expression] else [on_false]re ...

  9. Python基础之用PyQt5写一个tabview

    前面学习了menu的画图,现在学习tabview的画图,关于怎么打开designer.exe部分就不详细介绍了. 第一步:拖动一个Tab Widget控件到窗口去. 将控件拖上去之后就是这个样子,默认 ...

随机推荐

  1. 【Android编程】android平台的MITM瑞士军刀_cSploit源码解析及中间人攻击复现

    /文章作者:Kali_MG1937 作者博客ID:ALDYS4 QQ:3496925334 未经允许,禁止转载/ 何为MITM欺骗,顾名思义,中间人攻击的含义即为在局域网中充当数据包交换中间人的角色 ...

  2. canal+mysql+kafka实时数据同步安装、配置

    canal+mysql+kafka安装配置 概述 简介 canal译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 基于日志增量订阅和消费的业务包括 数 ...

  3. 身为一枚优秀的程序员必备的基于Redis的分布式锁和Redlock算法

    1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手锏功能,是基于Redi ...

  4. 孟老板 ListAdapter封装, 告别Adapter代码 (四)

    BaseAdapter系列 ListAdapter封装, 告别Adapter代码 (一) ListAdapter封装, 告别Adapter代码 (二) ListAdapter封装, 告别Adapter ...

  5. 音视频点播服务基础系列(Fmpeg常用命令)

    前言 公司业务中有一些场景需要用到服务端音视频剪辑技术,最开始为了快速上线使用的是某公有云的商用解决方案,但由于费用太高所以我们团队经过一个星期的冲刺,给出了一个FFmpeg+Serverless的解 ...

  6. CSS 奇思妙想 | 全兼容的毛玻璃效果

    通过本文,你能了解到 最基本的使用 CSS backdrop-filter 实现磨砂玻璃(毛玻璃)的效果 在至今不兼容 backdrop-filter 的 firefox 浏览器,如何利用一些技巧性的 ...

  7. 最多能创建多少个 TCP 连接?

    我是一个 Linux 服务器上的进程,名叫小进. 老是有人说我最多只能创建 65535 个 TCP 连接. 我不信这个邪,今天我要亲自去实践一下. 我走到操作系统老大的跟前,说: "老操,我 ...

  8. 二叉搜索树(Binary Search Tree)(Java实现)

    @ 目录 1.二叉搜索树 1.1. 基本概念 1.2.树的节点(BinaryNode) 1.3.构造器和成员变量 1.3.公共方法(public method) 1.4.比较函数 1.5.contai ...

  9. layui 监听checkbox 、radio、switch选中改变事件

    form.on('checkbox(filter)', function(data){ console.log(data.elem); //得到checkbox原始DOM对象 console.log( ...

  10. 重新整理 .net core 实践篇————cookie 安全问题[三十八]

    前言 简单整理一下cookie的跨站攻击,这个其实现在不常见,因为很多公司都明确声明不再用cookie存储重要信息,不过对于老站点还是有的. 正文 攻击原理: 这种攻击要达到3个条件: 用户访问了我们 ...