单击QTREEWIDGET时,请使用Qthread来防止冻结

发布于 2025-02-13 02:25:53 字数 3259 浏览 0 评论 0原文

每当用户单击qtreewidget中的项目时,计算机就会开始执行一些重型任务。我唯一的目标是使用QThread来防止冻结。


考虑以下代码:

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()
        
        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)
        
        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)
        
        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        
    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        time.sleep(2)
        self.label.setText(item.text(0))
        
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()

如何修改上述代码以防止冻结,以及最合适的方法是什么?


我尝试按照,第二个答案:

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()
        
        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)
        
        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)
        
        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        
    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        self.obj = Worker()
        self.thread = QThread()
        self.obj.finished.connect(self.change_text)
        self.obj.moveToThread(self.thread)
        self.obj.finished.connect(self.thread.quit)
        self.thread.started.connect(self.obj.work)
        self.thread.start()
    
    def change_text(self):
        self.label.setText(item.text(0))
        
class Worker(QObject):
    finished = pyqtSignal()
    @pyqtSlot()
    def work(self):
        time.sleep(2)
    finished = pyqtSignal()
        
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()

看起来我在做正确的事情。

Every time the user clicks on an item in QTreeWidget, the computer starts to perform some heavy duty tasks. My only objective is to use QThread to prevent freeze.


Consider the following code:

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()
        
        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)
        
        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)
        
        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        
    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        time.sleep(2)
        self.label.setText(item.text(0))
        
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()

How to modify the above code to prevent freeze and what is the most appropriate way of doing it?


I tried by following the protocol given in Background thread with QThread in PyQt, the second answer:

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()
        
        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)
        
        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)
        
        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        
    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        self.obj = Worker()
        self.thread = QThread()
        self.obj.finished.connect(self.change_text)
        self.obj.moveToThread(self.thread)
        self.obj.finished.connect(self.thread.quit)
        self.thread.started.connect(self.obj.work)
        self.thread.start()
    
    def change_text(self):
        self.label.setText(item.text(0))
        
class Worker(QObject):
    finished = pyqtSignal()
    @pyqtSlot()
    def work(self):
        time.sleep(2)
    finished = pyqtSignal()
        
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()

It does not look like I am doing the right thing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

避讳 2025-02-20 02:25:53

我进行了几次小调调整,以使您的工人课程正确运行。这将阻止其余的GUI冻结,但是取决于长期运行过程的标签文本将继续花费这么长时间才能更新。

同样,如果经常重复单独的线程中实现的任务,则可能需要考虑使用QthreadPool

我还提供了一些内联评论,以解释一些更改。

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()

        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)

        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)

        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        self.threads = []  # make shift threads container

    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        self.obj = Worker()
        thread = QThread()  
        self.obj.text = item.text(0) # the obj needs a copy of the text to emit
        self.obj.textReady.connect(self.change_text)
        self.obj.moveToThread(thread)
        self.obj.finished.connect(thread.quit)  
        thread.finished.connect(thread.deleteLater) # delete the threads once finished
        thread.started.connect(self.obj.work)
        thread.start()
        self.threads.append(thread)

    def change_text(self, text):
        self.label.setText(text)

class Worker(QObject):
    finished = pyqtSignal()
    textReady = pyqtSignal([str])

    @pyqtSlot()
    def work(self):
        time.sleep(2)
        self.textReady.emit(self.text) # emit the text that needs to be changed 
        self.finished.emit() 
                             
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()

I made a couple of minor adjustments to make your worker class run properly. This will prevent the rest of the gui from freezing but the label text that depends on the long running process will continue to take that long to update.

Also if the task implemented in the separate thread is repeated frequently you may want to consider using a QThreadPool.

I also included some inline comments to explain some of the changes.

from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('MainWindow')
        self.layout = QVBoxLayout()

        self.treewidget = MyTreeWidget()
        self.treewidget.itemClicked.connect(self.tree_click)
        self.layout.addWidget(self.treewidget)

        self.label = QLabel("Label", self)
        self.layout.addWidget(self.label)

        widget = QWidget()
        widget.setLayout(self.layout)
        self.setCentralWidget(widget)
        self.show()
        self.threads = []  # make shift threads container

    @pyqtSlot(QTreeWidgetItem)
    def tree_click(self, item):
        self.obj = Worker()
        thread = QThread()  
        self.obj.text = item.text(0) # the obj needs a copy of the text to emit
        self.obj.textReady.connect(self.change_text)
        self.obj.moveToThread(thread)
        self.obj.finished.connect(thread.quit)  
        thread.finished.connect(thread.deleteLater) # delete the threads once finished
        thread.started.connect(self.obj.work)
        thread.start()
        self.threads.append(thread)

    def change_text(self, text):
        self.label.setText(text)

class Worker(QObject):
    finished = pyqtSignal()
    textReady = pyqtSignal([str])

    @pyqtSlot()
    def work(self):
        time.sleep(2)
        self.textReady.emit(self.text) # emit the text that needs to be changed 
        self.finished.emit() 
                             
class MyTreeWidget(QTreeWidget):
    def __init__(self):
        super().__init__()
        item_1 = QTreeWidgetItem()
        item_1.setText(0, 'one item')
        item_2 = QTreeWidgetItem()
        item_2.setText(0,'another item')
        self.addTopLevelItem(item_1)
        item_1.addChild(item_2)
        self.setHeaderHidden(True)

if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    main = MainWindow()
    app.exec()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文