Add objects asynchronously to QGraphicsScene

4

I develop an application where a lot of objects need to be added to a QGraphicsScene object in order to represent the diagram of an electric power system. When the grid is large this process takes a while and the main window remains unresponsive. Hence, I'd like to know a way to create the objects asynchronously.

The following code is an very very simplified version of the actual code. In the example I create objects and I add them to the scene using the function add_objects. This is the function that should run in a thread.

import sys
from PySide2.QtWidgets import *
from PySide2.QtCore import *


def add_objects(scene: QGraphicsScene, n=1000):
    for i in range(n):
        item = QGraphicsEllipseItem(i * 5, 10, 60, 40)
        scene.addItem(item)


class MyView(QGraphicsView):
    def __init__(self):
        QGraphicsView.__init__(self)

        self.setGeometry(QRect(100, 100, 600, 250))

        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(QRectF())

        self.setScene(self.scene)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = MyView()
    view.show()
    add_objects(scene=view.scene, n=100)
    sys.exit(app.exec_())

------ EDIT --------

Since I've been asked for another example, here goes the complete case:

import sys
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from GridCal.Gui.GridEditorWidget import GridEditor
from GridCal.Engine.IO.file_handler import FileOpen


class AddObjectsThreaded(QThread):

    def __init__(self, editor: GridEditor, explode_factor=1.0):
        QThread.__init__(self)

        self.editor = editor

        self.explode_factor = explode_factor

    def run(self):
        """
        run the file open procedure
        """
        # clear all
        self.editor.diagramView.scene_.clear()

        # first create the buses
        for bus in self.editor.circuit.buses:
            bus.graphic_obj = self.editor.add_api_bus(bus, self.explode_factor)

        for branch in self.editor.circuit.branches:
            branch.graphic_obj = self.editor.add_api_branch(branch)

        # figure limits
        min_x = sys.maxsize
        min_y = sys.maxsize
        max_x = -sys.maxsize
        max_y = -sys.maxsize

        # Align lines
        for bus in self.editor.circuit.buses:
            bus.graphic_obj.arrange_children()
            # get the item position
            x = bus.graphic_obj.pos().x()
            y = bus.graphic_obj.pos().y()

            # compute the boundaries of the grid
            max_x = max(max_x, x)
            min_x = min(min_x, x)
            max_y = max(max_y, y)
            min_y = min(min_y, y)

        # set the figure limits
        self.editor.set_limits(min_x, max_x, min_y, max_y)
        #  center the view
        self.editor.center_nodes()


if __name__ == '__main__':
    app = QApplication(sys.argv)

    fname = r'1354 Pegase.xlsx'  # this file you need to download from https://github.com/SanPen/GridCal/tree/master/Grids_and_profiles/grids
    circuit = FileOpen(fname).open()

    view = GridEditor(circuit)
    view.resize(600, 400)
    view.show()

    thr = AddObjectsThreaded(editor=view)
    thr.start()

    sys.exit(app.exec_())

This process crases cleanly with the following error:

Process finished with exit code -1073740791 (0xC0000409)

python
python-3.x
qgraphicsscene
pyside2
asked on Stack Overflow Sep 24, 2019 by Santi Peñate-Vera • edited Sep 25, 2019 by Santi Peñate-Vera

1 Answer

0

According to other similar problems, the solution could be reinstalling pyqt, see here. These answers imply that obsolete versions of pyqt are the cause of this problem. In your case, since you are using PySide2 I suggest removing whatever version you currently have and installing again, if you're using pip:

pip uninstall PySide2
pip install --upgrade --no-cache-dir PySide2

In case that doesn't help, I've also found another similar error in a question that I hope would at least point you in the right direction that has an answer (which is probably already mentioned in the comments, don't add UI elements from other threads), I'm copying it here:

STATUS_STACK_BUFFER_OVERRUN is a /GS exception. They are thrown when Windows detects 'tampering' of a security cookie protecting a return address. It is probable that you are writing something past the end of a buffer, or writing something to a pointer that is pointing to the wrong place. However it is also possible that you have some dodgy memory or otherwise faulty hardware that is tripping validation code.

One thing that you could try is to disable the /GS switch (project properties, look for C/C++ -> Code Generation -> Buffer Security Check) and recompile. Running the code again may well cause an error that you can trap and trace. I think /GS is designed not to give you any info for security reasons.

Another thing you could do is run the code as is on a different PC and see if that fails, this may point to a hardware problem if it doesn't.

answered on Stack Overflow Oct 5, 2019 by Ofer Sadan

User contributions licensed under CC BY-SA 3.0