Pyqt5实现model/View,解决tableView出现空白行问题。
项目中表格需要显示5万条数据以上,并且实时刷新。开始使用的tableWidget,数据量一大显得力不从心,所以使用Qt的Model/View来重新实现。下面是更改之前编写的小Demo。
import sys from untitled import Ui_Form
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QAbstractTableModel, QModelIndex, QVariant, QThread, pyqtSignal class WorkThread(QThread):
scrollBottomSignal = pyqtSignal() def __init__(self, model):
super(WorkThread, self).__init__()
self.model = model
self.run_flag = True def run(self):
while self.run_flag:
row = self.model.rowCount()
self.model.insertRows(row, 1, QModelIndex())
self.scrollBottomSignal.emit()
self.usleep(1) # 不加延迟界面会卡顿。 def stop(self):
self.run_flag = False class MyTableModel(QAbstractTableModel):
def __init__(self):
super(MyTableModel, self).__init__()
self._data = [] # 要显示的数据
self._headers = ['行号', '姓名', '年龄', '性别'] # 表头
self.i = 0 def rowCount(self, parent=QModelIndex()):
"""
返回行数量。
"""
return len(self._data) def columnCount(self, parent=QModelIndex()):
"""
返回列数量。
"""
return len(self._headers) def insertRows(self, row, count, parent):
"""
插入行。
:param row: 插入起始行。
:param count: 插入行数量。
:param parent:
:return:
"""
self.beginInsertRows(QModelIndex(), row, row + count - 1)
for i in range(count):
self._data.insert(row, ['CZ', '25', '男'])
self.endInsertRows()
return True def removeRows(self, row, count, parent):
self.beginRemoveRows(QModelIndex(), 0, row + count - 1)
for i in range(count):
self._data.pop(row + count - 1 - i) # 倒着删
self.endRemoveRows() def clearView(self):
self.removeRows(0, self.rowCount(), QModelIndex()) def headerData(self, section, orientation, role):
"""
设置表头。
"""
if role == Qt.DisplayRole and orientation == Qt.Horizontal: # 限定只更改行表头
return self._headers[section] def data(self, index, role=Qt.DisplayRole):
if not index.isValid() or not 0 <= index.row() < self.rowCount():
return QVariant() row = index.row()
col = index.column() if role == Qt.DisplayRole:
if col == 0:
return str(row) # 行号
else:
return str(self._data[row][col-1]) # 数据
return QVariant() class MainUI(QWidget, Ui_Form):
def __init__(self):
super(MainUI, self).__init__()
self.setupUi(self)
self.workThread = None self.pushButton.clicked.connect(self.buttonClickedStart)
self.pushButton_2.clicked.connect(self.buttonClickedStop)
self.pushButton_3.clicked.connect(self.buttonClickedClear) self.model = MyTableModel()
self.tableView.setModel(self.model)
self.tableView.show() def buttonClickedStart(self):
"""开启线程,向表中插入数据。"""
self.workThread = WorkThread(self.model)
self.workThread.scrollBottomSignal.connect(self.scrollBottom)
self.workThread.start() def buttonClickedStop(self):
"""停止线程向表中插入数据。"""
self.workThread.stop() def buttonClickedClear(self):
"""清空表。"""
self.model.clearView() def scrollBottom(self):
"""右侧滑动条保持在最下面。"""
self.tableView.scrollToBottom() if __name__ == '__main__':
app = QApplication(sys.argv) ui = MainUI()
ui.show()
sys.exit(app.exec_())
程序运行起来之后的样子,速度是杠杠的:

功能:
(1)点击开始按钮表格开始刷数据。
(2)点击暂停按钮表格停止刷数据。
(3)点击清空按钮清空表格中的数据。
但是在测试过程中发现问题,在表中数据刷新时点击清空按钮,表格中会出现很多空行,如下图所示,这些空行不管我们怎么点击清空都删除不了。

这个问题卡了大概一天多,最后定位到原因,Qt中在子线程中不要操作界面,子线程中不要操作界面,子线程中不要操作界面,重要说三遍。
我将子线程更改成信号的形式增加数据已经解决此问题,下面是更改部分代码:
class WorkThread(QThread):
scrollBottomSignal = pyqtSignal()
addDataSignal = pyqtSignal() def __init__(self, model):
super(WorkThread, self).__init__()
self.model = model
self.run_flag = True def run(self):
while self.run_flag:
# row = self.model.rowCount()
# self.model.insertRows(row, 1, QModelIndex())
self.addDataSignal.emit()
self.scrollBottomSignal.emit()
self.usleep(1) # 不加延迟界面会卡顿。 def stop(self):
self.run_flag = False class MyTableModel(QAbstractTableModel):
... ...
def addData(self):
self.insertRows(self.rowCount(), 1, QModelIndex())
... ... class MainUI(QWidget, Ui_Form):
... ... def buttonClickedStart(self):
"""开启线程,向表中插入数据。"""
self.workThread = WorkThread(self.model)
self.workThread.addDataSignal.connect(self.model.addData)
self.workThread.scrollBottomSignal.connect(self.scrollBottom)
self.workThread.start() ... ...
Pyqt5实现model/View,解决tableView出现空白行问题。的更多相关文章
- PyQt学习随笔:Model/View中TableView视图数据项编辑结果及视图数据项的访问
按照<PyQt学习随笔:Model/View中设置视图数据项可编辑的方法>的方法支持视图数据可编辑后,编辑后的数据无需主动保存,PyQt会自动将界面变更的数据保存到对应的Model存储中, ...
- 解决TableView / ScrollView上的Menu问题(1滑出View区域还可点击2导致点击menu后View不能滑动)
解决TableView / ScrollView上的Menu问题 1划出区域还可点击 重写CCMenu的触摸事件函数 TouchBegin/TouchMove/TouchCancle/TouchEnd ...
- qt model/view 架构基础介绍之QListWidget
# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import * from Py ...
- MVC(Model View Controller)框架
MVC框架 同义词 MVC一般指MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一 ...
- 解决tableView中cell动态加载控件的重用问题
解决tableView中cell动态加载控件的重用问题 tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问 ...
- Qt 学习之路 2(41):model/view 架构
Qt 学习之路 2(41):model/view 架构 豆子 2013年1月23日 Qt 学习之路 2 50条评论 有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应 ...
- 第15.28节 PyQt(Python+Qt)入门学习:Model/View架构中的便利类QTableWidget详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 表格部件为应用程序提供标准的表格显示工具,在表格内可以管理基于行和列的数据项,表格中的最大 ...
- 第15.25节 PyQt(Python+Qt)入门学习:Model/View开发实战--使用QTableView展示Excel文件内容
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在前面的订阅专栏<第十九章.Model/View开发:QTableView的功能及属 ...
- 第15.24节 PyQt(Python+Qt)入门学习:Model/View架构中QTableView的作用及属性详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在Designer的部件栏Item Views中提供了PyQt和Qt已经实现好的table ...
随机推荐
- 2020 CCPC Wannafly Winter Camp Day1 C. 染色图
2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...
- Codeforces Round #627 (Div. 3) A - Yet Another Tetris Problem(逻辑)
题意 : 有n个高度,可以使任一高度加二任意次,问最终n个高度可否相同. 思路: 因为添加的2x1的方块不可旋转,只需考虑所有高度是否为同一奇偶性即可. #include <bits/stdc+ ...
- Codeforces Round #613 (Div. 2) A. Mezo Playing Zoma(逻辑)
题意: 给出一个移动序列,可以无效化一些指令,问可以移动到多少不同位置. 思路: 第一印象是统计左右指令数目,后来发现左右指令数目和即字符串长度. #include <bits/stdc++.h ...
- STL中去重函数unique
一:unique(a.begin(),a.end());去重函数只是去掉连续的重复值,对于不连续的值没有影响,SO,在使用前一般需要进行排序处理: 二: vector<int>::ite ...
- Codeforces Round #653 (Div. 3) B. Multiply by 2, divide by 6 (数学)
题意:有一个数\(n\),每次操作可以使\(n*=2\)或\(n/=6\)(如果能被整除),求最少操作次数使得\(n=1\),如果不满足,输出\(-1\). 题解:我们只要看\(n\)的质因子即可,如 ...
- 【luogu AT3957】[AGC023F] 01 on Tree
01 on Tree 题目链接:luogu AT3957 题目大意 有一棵根为 \(1\) 的树,每个节点有个值 \(0\) 或 \(1\). 然后每次你可以把一个没有父亲的点删除,然后把值放进一个数 ...
- Numpy Quickstart tutorial
此文是关于Numpy的一些基本用法, 内容来源于Numpy官网:https://docs.scipy.org/doc/numpy-dev/user/quickstart.html 1.The Basi ...
- linux多线程模拟银行家算法
题外话: 这应该是最近有点难度的作业了,起码比之前的理发师,读写,哲学家问题要难. 但是做好程序的结构,自顶向下,就还是不难的. 银行家算法简介: 代码: init() ...
- C# opc 功能相关
C# 程序里,使用 Interop.OPCAutomation.dll ,用于和opc通讯,读opc变量,写opc变量 链接: https://pan.baidu.com/s/1OpUa_Jct1gf ...
- Leetcode(11)-盛最多水的容器
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .画 n 条垂直线,使得垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0).找出其中的两条线,使得 ...