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)
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.
User contributions licensed under CC BY-SA 3.0