【问题标题】:MainWindow do not process events and user actions concurrentlyMainWindow 不会同时处理事件和用户操作
【发布时间】:2018-11-07 01:39:32
【问题描述】:

我有一个使用 Qt Designer 制作的 PyQt5 MainWindow。

这个窗口应该抓取一个站点,并在找到它们后在 TreeView 中列出抓取的链接。

我可以通过创建一个模型来做到这一点,QStandardItemModel 每次抓取新链接时,将所有链接添加到模型,然后使用 TreeView.setModel(model) 将模型设置为树,然后我会调用QtWidgets.qApp.processEvents()so 窗口已更新。当软件爬取站点时,窗口不会响应用户交互,直到执行QtWidgets.qApp.processEvents()

如何使用最新抓取的链接更新我的 TreeView,并且在抓取过程中我的窗口仍然难以处理?

这是我的代码

def start(self):
    ## start crawling
    self.populate_tree(crawled_links)

def populate_tree(self, links):
    data = []
    for index in links:
        item = (links[index]['from'], [])
        for link in links[index]['url']:
            item[1].append((link, []))
        data.append(item)
    model = QtGui.QStandardItemModel()
    self.__add_items(model, data)
    self.treeView.setModel(model)
    self.treeView.expandAll()
    self.treeView.scrollToBottom()
    self.treeView.setHeaderHidden(True)
    QtWidgets.qApp.processEvents()

def __add_items(self, model, data):
    for text, children in data:
        item = QtGui.QStandardItem(text)
        model.appendRow(item)
        if children:
            self.__add_items(item, children)

如果有任何帮助,crawled_links 列表如下所示:

crawled_links = {
0:{
    'url': {
        'one.html',
        'three.html'
        },
    'from':
        'site1.com'
    },
1:{
    'url': {
        'two.html'
        },
    'from':
        'site1.com'
    }
}

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qtreeview


    【解决方案1】:

    使用processEvents() 是一种不好的做法,它们只能用于某些特殊任务,并且如您所见并不能解决问题。

    解决方案是在一个线程上执行任务,并通过信号将其发送到GUI的线程。


    import threading
    
    from PyQt5 import QtCore, QtWidgets
    
    class Helper(QtCore.QObject):
         resultChanged = QtCore.pyqtSignal(dict)
    
         def start_crawling(self):
             crawled_links = {}
             # processing
             self.resultChanged.emit(crawled_links)
    
    
    class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
         def __init__(self, parent=None)
             QtWidgets.QMainWindow.__init__(self, parent)
             self.setupUi(self)
             self.helper = Helper()
             self.helper.resultChanged.connect(self.populate_tree)
    
         def start(self):
             # start crawling
             threading.Thread(target=self.helper.start_crawling, daemon=True).start()
    
    
         def populate_tree(self, crawled_links)
             ...
    

    【讨论】:

    • 非常感谢!我根本没有考虑穿线。这是我第一次编写这样的程序
    • 虽然这确实解决了我的问题,但我现在面临另一个问题。我想在线程到达登录页面时暂停线程,以便可以打开登录对话框以获取用户凭据,然后在登录成功时恢复线程。我该怎么做?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多