我是新来的。目前,我正在尝试学习如何从不同的线程更新表模型,然后如何为其立即获得显示更新。我阅读了文档,发现了dataChanged()
和layoutChanged()
信号。虽然dataChanged()
工作正常,但任何发出layoutChanged()
的尝试都会失败,原因是:
'QObject::connect: Cannot queue arguments of type 'QList<QPersistentModelIndex>' (Make sure 'QList<QPersistentModelIndex>' is registered using qRegisterMetaType().)
搜索这个特定的错误并没有给我任何可以转化为工作代码的东西。我没有显式地使用任何QList
或QPersistentModelIndex
,但是由于我选择的构造,当然可以隐式地使用它们
我做错了什么
class TimedModel(QtCore.QAbstractTableModel):
def __init__(self, table, view):
super(TimedModel, self).__init__()
self.table = table
self.view = view
self.setHeaderData(0, Qt.Horizontal, Qt.AlignLeft, Qt.TextAlignmentRole)
self.rows = 6
self.columns = 4
self.step = 5
self.timer = Thread(
name = "Timer",
target = self.tableTimer,
daemon = True)
self.timer.start()
self.random = Random()
self.updated = set()
@staticmethod
def encode(row, column):
return row << 32 | column
def data(self, index, role):
if role == Qt.DisplayRole or role == Qt.EditRole:
return f'Data-{index.row()}-{index.column()}'
if role == Qt.ForegroundRole:
encoded = TimedModel.encode(index.row(), index.column())
return QBrush(Qt.red if encoded in self.updated else Qt.black)
return None
def rowCount(self, index):
return self.rows
def columnCount(self, index):
return self.columns
def headerData(self, col, orientation, role):
if orientation == Qt.Vertical:
# Vertical
return super().headerData(col, orientation, role)
# Horizontal
if not 0 <= col < self.columns:
return None
if role == Qt.DisplayRole:
return f'Data-{col}'
if role == Qt.TextAlignmentRole:
return int(Qt.AlignLeft | Qt.AlignVCenter)
return super().headerData(col, orientation, role)
def tableTimer(self):
while True:
time.sleep(5.0)
randomRow = self.random.randint(0, self.rows)
randomColumn = self.random.randint(0, self.columns)
encodedRandom = TimedModel.encode(randomRow, randomColumn)
if encodedRandom in self.updated:
self.updated.remove(encodedRandom)
else:
self.updated.add(encodedRandom)
updatedIndex = self.createIndex(randomRow, randomColumn)
self.dataChanged.emit(updatedIndex, updatedIndex)
'''this here does not work:'''
self.layoutAboutToBeChanged.emit()
self.rows += self.step
self.layoutChanged.emit()
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.timedTable = QTableView()
self.model = TimedModel(self.timedTable, self)
self.timedTable.setModel(self.model)
headerView = self.timedTable.horizontalHeader()
headerView.setStretchLastSection(True)
self.setCentralWidget(self.timedTable)
self.setGeometry(300, 300, 1000, 600)
self.setWindowTitle('Timed Table')
self.show()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.name = "Timed Table Application"
window = MainWindow()
window.show()
app.exec_()
以下代码:
创建与
QPersistentModelIndex
关联的新模型元素,这些元素不是线程安全的,并且Qt监视其创建以警告其误用,就像在本例中一样,因为修改该元素是不安全的,因为它意味着从另一个线程修改GUI(有关详细信息,请阅读here)因此,您会看到一条消息,警告您正在尝试的操作是不安全的
相反
dataChanged
只发出一个信号,不创建任何属于Qt的元素,幸运的是,修改“self.updated”并没有产生瓶颈,因为您从辅助线程修改了属于主线程的属性,而没有将保护用作互斥体Qt指出,GUI和GUI使用的元素只应在GUI线程中更新,如果您想使用其他线程的信息修改GUI,则必须发送该信息,例如,使用线程安全的信号:
相关问题 更多 >
编程相关推荐