美文网首页
《从子线程中回调更新tableview》报错 Cannot cr

《从子线程中回调更新tableview》报错 Cannot cr

作者: 昵称违法 | 来源:发表于2019-10-25 16:29 被阅读0次

描述:在主UI线程中,启动了一个子线程进行计算,计算完毕,回调更新UI中的一个tabelview。界面已经更新,但是线程出现报错。

程序结构

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QHeaderView(0x1ec5ce55eb0), parent's thread is QThread(0x1ec4d609c30), current thread is BigWorkThread(0x1ec5cdd4820)
QBasicTimer::start: Timers cannot be started from another thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QHeaderView(0x1ec5ce58d70), parent's thread is QThread(0x1ec4d609c30), current thread is BigWorkThread(0x1ec5cdd4820)
QBasicTimer::start: Timers cannot be started from another thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTableView(0x1ec4d629d40), parent's thread is QThread(0x1ec4d609c30), current thread is BigWorkThread(0x1ec5cdd4820)

以下是回调函数:

    #线程计算完毕,回调,显示计算结果    
    def display_result_df_callBack(self, df):
        model = pandasModel(df)
        view = self.tableView_result
        view.setModel(model)          #调试后发现,这一句是报错的根源
        view.show()        
        logging.info("回调函数")

查询后发现:
It is not good to access the model directly from another thread since the QObjects are not thread-safe, instead it creates a QObject that sends the data to the main thread through signals, in this case for a simple operation I created the slot update_item that receives the row, column and data.

How to correctly update view in pyQt after editing abstract model in another thread?

import sys
import threading
import time

from PyQt5 import QtCore, QtGui, QtWidgets


class CopterDataModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None):
        super(CopterDataModel, self).__init__(parent)
        self.data_contents = [[1, 2]]

    def rowCount(self, n=None):
        return len(self.data_contents)

    def columnCount(self, n=None):
        return 2

    def data(self, index, role):
        row = index.row()
        col = index.column()
        # print('row {}, col {}, role {}'.format(row, col, role)) #for debug
        if role == QtCore.Qt.DisplayRole:
            return self.data_contents[row][col] or ""

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if not index.isValid():
            return False

        if role == QtCore.Qt.EditRole:
            self.data_contents[index.row()][index.column()] = value
            print("edit", value)
            self.dataChanged.emit(
                index, index, (QtCore.Qt.EditRole,)
            )  # NOT WORKING
        else:
            return False
        return True

    def flags(self, index):
        return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled

    @QtCore.pyqtSlot(int, int, QtCore.QVariant)
    def update_item(self, row, col, value):
        ix = self.index(row, col)
        self.setData(ix, value)


class SignalManager(QtCore.QObject):
    fooSignal = QtCore.pyqtSignal(int, int, QtCore.QVariant)


if __name__ == "__main__":

    def timer(obj):
        idc = 1001
        while True:
            obj.fooSignal.emit(0, 0, idc)
            idc += 1
            time.sleep(1)

    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)

    foo = SignalManager()

    tableView = QtWidgets.QTableView()
    myModel = CopterDataModel()
    foo.fooSignal.connect(myModel.update_item)

    tableView.setModel(myModel)

    tableView.show()

    t = threading.Thread(target=timer, args=(foo,), daemon=True)
    t.start()

    app.exec_()

解决方法
线程中在定义一个信号(名字:displayResultAfterCalculating(list)----计算完毕显示计算结果,返回一个list,list中装一个dataframe)
线程计算完毕后:带上计算结果,发送一个该信号
主线程接收信号,并用该计算结果更新ui
结束!!!!

相关文章

  • 《从子线程中回调更新tableview》报错 Cannot cr

    描述:在主UI线程中,启动了一个子线程进行计算,计算完毕,回调更新UI中的一个tabelview。界面已经更新,但...

  • Android ble蓝牙问题

    声明:本文摘抄自博客园 (1)蓝牙回调安卓4.4的蓝牙回调是在异步线程中(不在主线程),若要在蓝牙回调中执行更新界...

  • 蓝牙ble开发注意事项

    (1)蓝牙回调 安卓4.4的蓝牙回调是在异步线程中(不在主线程),若要在蓝牙回调中执行更新界面的操作,记得切换到主...

  • Android更新UI的几种方法

    第一种场景: 在UI线程中更新UI,这种是最简单的,直接更新UI即可。代码如下 第二种场景: 从子线程中更新UI ...

  • 异步消息处理

    异步消息处理 android耗时操作只能放在非主线程,message从子线程进入主线程,从不能更新UI到更新UI,...

  • iOS指纹解锁后更新UI问题

    昨天在公司需求中需要加入指纹解锁功能 在指纹接受验证后 回调会在子线程中 因此需要调用主线程执行ui更新 然鹅...

  • iOS学习笔记(持续更新)

    1.主线程中更新UI 之前在项目中的一个回调方法里面更新了UI导致了一个NSInternalInconsisten...

  • Android不在子线程更新UI

    报错 UI 的线程检查机制就已经建立了,所以在子线程更新就会报错。 子线程更新的错误定位 子线程更新的错误定位是 ...

  • AFN 同步请求

    需要把AFN的回调 放置在子线程 AFN的回调 默认在主线程,如果不把回调设置子线程, 那么 dispatch_s...

  • YTKNetwork的指定回调线程缺失

    AFNetworking指定completionQueue可以指定回调的线程.YTKNetwork写死了主线程回调...

网友评论

      本文标题:《从子线程中回调更新tableview》报错 Cannot cr

      本文链接:https://www.haomeiwen.com/subject/iuzsvctx.html