python - 使用 QAbstractTableModel 在 pyqts QTableView 中插入和删除行

标签 python pyqt qtableview qabstracttablemodel

如何使用 QAbstractTableModel 在 QTableView 中插入和删除单行。

一个新行将在一个单独的线程中给出,该线程通过 pyqtsignal 连接到 QAbstractTableModel。 目标是每次给出新的发出时添加一行。如果表达到最大行数 10 行,则应添加新发出的行并删除第一行。所以我有一个最大长度为 10 个条目的运行表。

目前,除了删除和添加行之外,一切正常

import sys
import time
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QAction, QTableView
from PyQt5.QtCore import QSize, Qt,QAbstractTableModel, pyqtSlot, pyqtSignal, QThread

import sys
import time
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QAction, QTableView
from PyQt5.QtCore import QSize, Qt,QAbstractTableModel, pyqtSlot, pyqtSignal, QThread

class Table(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.resize(800, 600)
        self.setMinimumSize(QSize(800, 600))

        self.table = QTableView()
        self.setCentralWidget(self.table)

        toolbar = QToolBar("Toolbar")
        con = QAction("Connect", self)
        con.triggered.connect(self.updateTable)
        discon = QAction("Disconnect", self)
        discon.triggered.connect(self.terminateThread)

        toolbar.addAction(con)
        toolbar.addAction(discon)
        self.addToolBar(toolbar)

    def updateTable(self):
        print("Connect")
        data = [
            ["This", "is", "test", 1],
            ["This", "is", "test", 2],
            ["This", "is", "test", 3],
        ]

        self.model = TableModel(data)
        self.table.setModel(self.model)

        self.thread = QTableThread()
        self.thread.sig1.connect(self.model.addRow)
        self.thread.start()

    def terminateThread(self):
        self.thread1.terminate()

class QTableThread(QThread):
    sig1 = pyqtSignal(list)

    def __init__(self):
        super(QTableThread, self).__init__()
        self.count = 4

    def run(self):
        for i in range(20):
            self.sig1.emit(["This", "is", "test", self.count])
            self.count += 1
            time.sleep(0.5)

class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self._data[index.row()][index.column()]

    def rowCount(self, index):
        return len(self._data)

    def columnCount(self, index):
        return len(self._data[0])

    @pyqtSlot(list)
    def addRow(self,status):
        print(status)
        # What to implement here?


if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Table()
    win.show()
    sys.exit( app.exec_() )

最佳答案

我为您标记了我所做更改的行。尝试一下:

import sys
#import time
from PyQt5.QtWidgets import QApplication, QMainWindow, QToolBar, QAction, QTableView
from PyQt5.QtCore import (QSize, Qt, QAbstractTableModel, pyqtSlot, pyqtSignal, 
    QThread, QModelIndex)


class QTableThread(QThread):
    sig1 = pyqtSignal(list)

    def __init__(self):
        super(QTableThread, self).__init__()
        self.count = 4

    def run(self):
        for i in range(20):
            self.sig1.emit(["This", "is", "test", self.count])
            self.count += 1
            self.msleep(500)                                            # !!!


class TableModel(QAbstractTableModel):
    def __init__(self, _data):
        super(TableModel, self).__init__()
        self._data = _data

    def data(self, index, role):
        if role == Qt.DisplayRole:
            return self._data[index.row()][index.column()]

    def rowCount(self, index=QModelIndex()):                     # +
        return  0 if index.isValid() else len(self._data)        # +

    def columnCount(self, index=QModelIndex()):                  
        return len(self._data[0])

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    def insertRows(self, new_row, position, rows, parent=QModelIndex()):
        position = (position + self.rowCount()) if position < 0 else position
        start = position
        end = position + rows - 1

        if end <= 8:
            self.beginInsertRows(parent, start, end)
            self._data.append(new_row) 
            self.endInsertRows()
            return True
        else:
            self.beginInsertRows(parent, start, end)
            self._data.append(new_row) 
            self.endInsertRows()
            self.removeRows(0, 0)
            return True

    def removeRows(self, position, rows, parent=QModelIndex()):
        start, end = position, rows 
        self.beginRemoveRows(parent, start, end)
        del self._data[start:end + 1]
        self.endRemoveRows()
        return True
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


class Table(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.resize(800, 600)
        self.setMinimumSize(QSize(800, 600))

        self.table = QTableView()
        self.setCentralWidget(self.table)

        toolbar = QToolBar("Toolbar")
        con = QAction("Connect", self)
        con.triggered.connect(self.updateTable)
        discon = QAction("Disconnect", self)
        discon.triggered.connect(self.terminateThread)

        toolbar.addAction(con)
        toolbar.addAction(discon)
        self.addToolBar(toolbar)
        
        self.thread = None                                                             # +++

    def updateTable(self):
        print("Connect")
        data = [
            ["This", "is", "test", 1],
            ["This", "is", "test", 2],
            ["This", "is", "test", 3],
        ]
        self.model = TableModel(data)
        self.table.setModel(self.model)

        self.thread = QTableThread()
#        self.thread.sig1.connect(self.model.addRow)                                    # ---
        self.thread.sig1.connect(lambda new_row: self.model.insertRows(new_row, -1, 1)) # +++
        self.thread.start()

    def terminateThread(self):
        if self.thread and self.thread.isRunning():                                     # +++
            self.thread.terminate()
        

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = Table()
    win.show()
    sys.exit( app.exec_() )

enter image description here

关于python - 使用 QAbstractTableModel 在 pyqts QTableView 中插入和删除行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65320933/

相关文章:

python - 如何在 ubuntu 上安装 python 模块 sys、os 和 getopt?

Python二叉树实现插入方法: help required

python-3.x - 在另一台计算机上运行卡住的 pyqt 应用程序时不显示图像

Python time.sleep(1) 立即完成

python - 将 sklearn 的 BaggingClassifier 与 GridSearchCV 一起使用时出现 ZeroDivisionError

Python PyQt5 - QEvent Keypress 执行两次

c++ - QTableView 行删除

QTableView:dataChanged 事件清除正在编辑的单元格

css - QTableView 小部件的 Qt 样式表中有哪些可用选项?

python属性错误: object has no attribute