Create a tree using threads

Heads up! You've already completed this tutorial.

GiUnZ | 2021-06-27 18:56:12 UTC | #1

I am trying to create an application that will be getting data through an API and present them in QTreeView, using PySide6. As it takes a long time to get the data I want to retrieve them using a QThread. My example code is the following: import logging import time

python
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *

logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    level=logging.INFO)

class MainWindow(QMainWindow):
    gettingData = False
    counting = False


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.counter = 0

        layout = QVBoxLayout()


        self.b = QPushButton("Start Counting with a Thread")
        self.bt1 = QPushButton("Generate tree with Thread")
        self.bt2 = QPushButton("Generate tree without a Thread")
        self.tree = QTreeView()

        layout.addWidget(self.b)
        layout.addWidget(self.bt1)
        layout.addWidget(self.bt2)
        layout.addWidget(self.tree)
        self.b.clicked.connect(self.startCounting)
        self.bt1.clicked.connect(self.startGenerating)
        self.bt2.clicked.connect(self.startGenerating2)

        w = QWidget()
        w.setLayout(layout)

        self.setCentralWidget(w)

        self.show()

        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

    def startCounting(self):
        thread = Thread(self.counting)
        thread.signal.signal.connect(self.something)
        self.threadpool.start(thread)

    def something(self, signal):
        if signal == "False":
            logging.info("Counting is Complete")
        else:
            logging.info(signal)

    def startGenerating(self):
        thread = DataThread()
        thread.signals.signal_QStandardItemModel(self.treeAction)
        self.threadpool.start(thread)

    def treeAction(self,signal):
        self.tree.setModel(signal)

    def startGenerating2(self):
        start = time.perf_counter()
        siteTreeViewModel = QStandardItemModel()
        rootNode = siteTreeViewModel.invisibleRootItem()
        aItem = TreeStandardItem("A")
        bItem = TreeStandardItem("B")
        cItem = TreeStandardItem("C")
        rootNode.appendRow(aItem)
        time.sleep(3)
        rootNode.appendRow(bItem)
        time.sleep(3)
        bItem.appendRow(cItem)
        self.tree.setModel(siteTreeViewModel)
        end = time.perf_counter() - start
        logging.info("Generated tree in "+str(end))



class Thread(QRunnable):

    def __init__(self, counting):
        super().__init__()
        self.counting = counting
        self.signal = Signal()

    def run(self):
        for x in range(10):
            self.signal.signal.emit(str(x))
            time.sleep(.1)
        counting = False
        self.signal.signal.emit(str(counting))

class Signal(QObject):
    signal = Signal(str)

class DataThread(QRunnable):

    def __init__(self):
        super().__init__()
        self.signals = WorkerSignals()

    def run(self):
        logging.info("Start generating the tree")

        start = time.perf_counter()
        siteTreeViewModel = QStandardItemModel()
        rootNode = siteTreeViewModel.invisibleRootItem()
        aItem = TreeStandardItem("A")
        bItem = TreeStandardItem("B")
        cItem = TreeStandardItem("C")
        rootNode.appendRow(aItem)
        time.sleep(2)
        rootNode.appendRow(bItem)
        time.sleep(2)
        bItem.appendRow(cItem)
        end = time.perf_counter() - start
        self.signals.signal_QStandardItemModel.emit(siteTreeViewModel)
        logging.info("Generated tree in "+str(end))
        self.signals.finished.emit()

class TreeStandardItem(QStandardItem):
    def __init__(self, txt=''):
        super().__init__()
        self.setEditable = False
        self.setForeground(QColor(255, 255, 255))
        self.setText(txt)

class WorkerSignals(QObject):
    signal_QStandardItemModel = Signal()
    finished = Signal()

app = QApplication([])
window = MainWindow()
app.exec()

The first counting button works as expected creating a thread. Generating the tree without a thread, confirms that the code I am trying to run using a thread is working Once I try running the tree generation using thread, I get the following error:

python
Traceback (most recent call last):
  File "/home/giunz/code/tutorial/threaded-tree-01.py", line 61, in startGenerating
    thread.signals.signal_QStandardItemModel(self.treeAction)
TypeError: 'Signal' object is not callable

Any help on how to generate the tree using a thread, would be appreciated.

Thanks in advance


Over 10,000 developers have bought Create GUI Applications with Python & Qt!
Create GUI Applications with Python & Qt6
Take a look

Downloadable ebook (PDF, ePub) & Complete Source code

Also available from Leanpub and Amazon Paperback

[[ discount.discount_pc ]]% OFF for the next [[ discount.duration ]] [[discount.description ]] with the code [[ discount.coupon_code ]]

Purchasing Power Parity

Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]
Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak
Martin Fitzpatrick

Create a tree using threads was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular https://www.martinfitzpatrick.com/browse/books/ on the subject.