【问题标题】:Add objects asynchronously to QGraphicsScene将对象异步添加到 QGraphicsScene
【发布时间】:2020-01-24 21:22:58
【问题描述】:

我开发了一个应用程序,其中需要将大量对象添加到 QGraphicsScene 对象中以表示电力系统图。当网格很大时,此过程需要一段时间,并且主窗口仍然无响应。因此,我想知道一种异步创建对象的方法。

以下代码是actual code 的一个非常简化的版本。在示例中,我创建对象并使用函数add_objects 将它们添加到scene。这是应该在线程中运行的函数。

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_())

-------- 编辑--------

因为有人问我另一个例子,这里是完整的例子:

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_())

这个过程干净利落地出现以下错误:

进程以退出代码 -1073740791 (0xC0000409) 结束

【问题讨论】:

  • 您提供的代码会产生这个问题吗?我已经执行了它,而不是我。如果您需要帮助提供一个真实的minimal reproducible example,另一方面放弃使用线程来加载项目,因为这是不可能的,也许一个选项是每 T 毫秒加载一个项目。
  • 确实代码没有重现任何问题。我已经尝试过线程,但我这样做的方式(即从线程类运行函数)不起作用。因此问题。有没有办法做到这一点,或者让主窗口保持响应?
  • 查看新示例
  • 这对我来说崩溃了:xlrd.biffh.XLRDError:不支持的格式,或损坏的文件:预期的 BOF 记录;找到 b'\n\n\n\n\n\n
  • 必须关闭某些东西...来自github.com/SanPen/GridCal/tree/master/Grids_and_profiles 的任何其他文件也可以

标签: python python-3.x qgraphicsscene pyside2


【解决方案1】:

根据其他类似问题,解决办法可能是重装pyqt,见here。这些答案意味着pyqt 的过时版本是导致此问题的原因。就您而言,由于您使用的是 PySide2,因此如果您使用的是 pip,我建议您删除当前拥有的任何版本并重新安装:

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

如果这没有帮助,我还在一个问题中发现了另一个类似的错误,我希望至少能指出你正确的direction 有一个答案(这可能已经在 cmets 中提到,不要从其他线程添加 UI 元素),我在这里复制它:

STATUS_STACK_BUFFER_OVERRUN 是 /GS 异常。当 Windows 检测到保护返回地址的安全 cookie 被“篡改”时,它们就会被抛出。您可能正在写入超出缓冲区末尾的内容,或者将内容写入指向错误位置的指针。但是,您也可能有一些不可靠的内存或其他有故障的硬件会触发验证代码。

您可以尝试的一件事是禁用 /GS 开关(项目属性,查找 C/C++ -> 代码生成 -> 缓冲区安全检查)并重新编译。再次运行代码很可能会导致您可以捕获和跟踪的错误。我认为 /GS 旨在出于安全原因不向您提供任何信息。

您可以做的另一件事是在另一台 PC 上按原样运行代码,看看是否失败,如果没有,这可能表明硬件问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多