[英]QUiLoader crashes with custom widgets in PySide
I am trying to embed a PySide PyQtGraph widget into a GraphicsView window created with QT Creator. 我正在尝试将PySide PyQtGraph小部件嵌入到使用QT Creator创建的GraphicsView窗口中。 However, a segmentation error occurs when I import the UI file and use the "promote to" functionality in QT Creator.
但是,当我导入UI文件并在QT Creator中使用“升级为”功能时,会发生分段错误。
This error has been observed previously and a work-around to override the QUiLoader's createWidget() has been proposed: 以前已经观察到此错误,并提出了一种替代方法来覆盖QUiLoader的createWidget():
http://www.mail-archive.com/pyside@qt-project.org/msg00306.html http://www.mail-archive.com/pyside@qt-project.org/msg00306.html
and 和
Calling custom class in .ui file fails 在.ui文件中调用自定义类失败
However, when I implement the workaround I still end up with a segmentation error. 但是,当我实施变通办法时,仍然会遇到细分错误。
Does anyone know why this workaround does not seem to work in my code? 有谁知道为什么这种解决方法似乎无法在我的代码中起作用? Or is there another way to embed a PyQtGraph while importing a UI file dynamically?
还是在动态导入UI文件时嵌入PyQtGraph的另一种方法?
Many thanks, 非常感谢,
Taco 塔克
Some example code: 一些示例代码:
#!/usr/bin/python
import os
import sys
from PySide.QtUiTools import QUiLoader
import pyqtgraph as pg
SCRIPT_DIRECTORY = os.path.dirname(os.path.abspath(__file__))
class UiLoader(QUiLoader):
def __init__(self, baseinstance):
QUiLoader.__init__(self, baseinstance)
self.baseinstance = baseinstance
def createWidget(self, className, parent = None, name = ""):
if className in QUiLoader.availableWidgets(self):
widget = QUiLoader.createWidget(self, className, parent, name)
else:
if hasattr(self.baseinstance, "customWidgets"):
if className in self.baseinstance.customWidgets.keys():
widget = self.baseinstance.customWidgets[className](parent)
else:
raise KeyError("Unknown widget '%s'" % className)
else:
raise AttributeError("Trying to load custom widget '%s', but base instance '%s' does not specify custom widgets." % (className, repr(self.baseinstance)))
if self.baseinstance is not None:
setattr(self.baseinstance, name, widget)
return widget
def loadUi(uifile, baseinstance=None):
loader = UiLoader(baseinstance)
loader.registerCustomWidget(pg.PlotWidget)
widget = loader.load(uifile)
QMetaObject.connectSlotsByName(widget)
return widget
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.ui = loadUi(os.path.join(SCRIPT_DIRECTORY, 'example1.ui'), self)
self.ui.plotBtn.clicked.connect(self.PlotTest)
def PlotTest(self):
self.ui.plottest.plot(np.random.normal(size=50), clear=True)
def main():
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
if __name__ == '__main__':
main()
And the UI file: example1.ui 和UI文件:example1.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="PlotWidget" name="centralwidget">
<widget class="QGraphicsView" name="graphicsView">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>761</width>
<height>471</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="plotBtn">
<property name="geometry">
<rect>
<x>670</x>
<y>510</y>
<width>114</width>
<height>32</height>
</rect>
</property>
<property name="text">
<string>Plot</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<customwidgets>
<customwidget>
<class>PlotWidget</class>
<extends>QWidget</extends>
<header>pyqtgraph</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
You can circumvent PySides issues with QtUiLoader by using pg.Qt.loadUiType('uicfile.ui')
. 您可以使用
pg.Qt.loadUiType('uicfile.ui')
来解决QtUiLoader的PySides问题。 Here is an example based on your code: 这是一个基于您的代码的示例:
from PySide.QtGui import *
import pyqtgraph as pg
import numpy as np
formClass, baseClass = pg.Qt.loadUiType('example1.ui')
class MainWindow(baseClass):
def __init__(self, parent=None):
baseClass.__init__(self, parent)
self.ui = formClass()
self.ui.setupUi(self)
self.setCentralWidget(self.ui.centralwidget)
self.ui.plotBtn.clicked.connect(self.PlotTest)
def PlotTest(self):
self.ui.centralwidget.plot(np.random.normal(size=50), clear=True)
def main():
app = QApplication.instance()
if app is None:
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
if __name__ == '__main__':
main()
Notes: 笔记:
Your .ui file seems to be built improperly--you promoted the 'centralwidget' to be a PlotWidget, whereas I think you intended the GraphicsView to be promoted instead. 您的.ui文件似乎构建不正确-您将'centralwidget'提升为PlotWidget,而我认为您打算将GraphicsView提升。
I ran into some unicode issues with loadUiType
and had to use the latest pyqtgraph development version. 我在使用
loadUiType
遇到了一些unicode问题,不得不使用最新的pyqtgraph开发版本。 You might need to do the same. 您可能需要做同样的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.