尝试复制pyside对象时出现问题



我有一个相当令人沮丧的问题使用pyside,我欢迎任何建议。

首先,一些上下文

我使用Qt Designer创建了一个简单的GUI,我已经使用pyside-uic.exe到我的.ui文件上,以便生成相关的Python文件。

我用 Python 3.3 pyside 1.2.1 " Qt设计器4 ( Qt 4.8.5 )。

我使用下面的代码来启动我的GUI:

class my_dialog(QMainWindow, my_gui.Ui_main_window):
    def __init__(self, parent=None):
        super(my_dialog, self).__init__(parent)
        self.setupUi(self)
if ("__main__" == name):
    app = QApplication(sys.argv)
    main_dialog = my_dialog()
    # (1)
    main_dialog.show()
    sys.exit(app.exec_())

我想要实现的

我的GUI有几个选项卡。选项卡的数量不是预先确定的,而是在运行时评估的。因此,我决定在Qt Designer中创建一个选项卡,用作模板。

第一次我需要添加一个选项卡时,我修改了这个模板,如果我需要任何额外的选项卡,我计划在复制该选项卡,然后适当地修改该副本

我遇到的问题

我的问题是我似乎找不到复制标签小部件的方法。经过一番研究,我认为copy模块(或pickle模块,见编辑)可能会做到这一点(以下代码插入(1)):

new_tab = copy.deepcopy(main_dialog.my_tab)
main_dialog.my_tabs.addTab(new_tab, "")

但是触发了以下错误:

    main_dialog.my_tabs.addTab(new_tab, "")

RuntimeError:内部c++对象(Pyside.QtGui.QWidget)已经删除

我自己能找到的

我在SO和其他网站上看到,当使用pyside时,可能存在收集对象的问题,因为在Python中没有对它们的引用。

然而,事实仍然是,即使我将这段代码移动到由pyside生成的.py文件中的setupUi()方法中,我仍然得到完全相同的错误。

还值得注意的是,我能够访问my_tab对象来修改其内容,而没有任何麻烦。

我能够在我的代码中从头开始创建另一个选项卡,main_dialog.my_tabs.addTab(new_tab, "")在该上下文中工作得非常好。

经过一些实验,我意识到问题可能发生在my_tab对象的副本上。实际上,在复制我刚刚创建的选项卡对象时,我可以看到尝试将副本添加到GUI选项卡也失败了,并且出现了相同的错误。

看起来拷贝失败了,或者对象由于某种原因被立即删除了。这就是我想说的……

我的问题

考虑到所有这些,我想找到一种方法来成功地复制对象,找到另一种方法来使用现有的pyside对象作为其他类似对象的模板。

可以当然从生成的文件中取出选项卡的代码并编写我自己的addTab()方法。但是,我希望从现有的.ui文件构建,并避免硬编码GUI元素。

编辑:

当使用pickle:

new_tab = pickle.loads(pickle.dumps(main_dialog.my_tab, -1))

我得到以下错误:

    new_tab = pickle.loads(pickle.dumps(main_dialog.my_tab, -1))

_pickle。PicklingError: cannot pickle :属性查找Pyside.QtCore.SignalInstance failed.

为要复制的小部件创建单独的ui文件的建议似乎是一个合理的解决方案。虽然使用pyside-ui为小部件生成一个单独的gui模块似乎与使用QUiLoader一样好(实际上,它会稍微更有效)。

至于为什么使用copy.deepcopy克隆小部件不起作用的问题:这是因为它只会复制python包装器,而不是底层的c++对象。

经过进一步的研究,我认为使用这些技术之一复制pyside对象是不可能的。

首先要注意的是,没有内置函数来克隆Qt小部件,因此克隆应该使用copy, picklemarshal等模块来完成。

使用picklemarshal失败,因为对象被发现不可拾取

虽然copy.copycopy.deeepcopy没有引发任何警告/异常/错误,但复制没有发生,或者由于某种原因在之后被删除。

当试图将deepcopy作为参数传递给addTab时,没有抛出警告/异常/错误,但程序在该行停止并退出回Python命令提示符。在退出之前,这一行需要几秒钟的时间,这一事实使我假设deepcopy试图浏览对象属性并在某些时候失败。对copy做同样的操作会导致问题中提到的前面的C++ object deleted错误,所以我只能推断deepcopy操作失败。

因此,我能给寻找类似答案的人的唯一建议是实现他们自己的copy-widget函数,这最终是我现在要做的。

仍然,我希望理解deepcopy是如何这样失败的,如此无声,却引发了执行的结束。我开始了一个线程,试图找到一个答案,这个

编辑:

我找到了这个问题的解决方案,它尊重我的要求,不硬编码GUI元素和使用Qt设计器创建可重复元素的GUI和模板。我希望它能帮助任何有同样问题的人:

这个想法是有可能使用Qt和pyside在运行时使用QUiLoader()方法加载给定的.ui文件。因此,可以解析.ui文件以提取给定的小部件(.ui文件是简单的XML文件),并使用以下代码来使用它:

loader = QUiLoader()
ui_file = QFile("path_to_ui_file.ui")
ui_file.open(QFile.ReadOnly)
new_tab = loader.load(ui_file)
ui_file.close()
main_dialog.my_tabs.addTab(new_tab, "")

它有效!

关于上面例子的几点说明:

  • 第二行假设您已经将小部件隔离在文件path_to_ui_file.ui
  • 在我的例子中,小部件是一个选项卡,当然它可以与任何小部件一起工作,最后一行只是为了显示不再抛出错误
  • 最后,这种方法的优点是允许您使用像Qt Designer这样的工具来开发您的GUI元素,即使涉及到一些变量,例如您想要多少选项卡?

相关内容

  • 没有找到相关文章

最新更新