2016-08-05 130 views
1

使用PyQt4的uic.loadUi,我想加载.ui文件并在其中使用自定义小部件。这意味着使用uic.loadUi的第三个package参数,该参数将导入包含自定义窗口小部件类的包。如何使用自定义小部件和uic.loadUi而不导入自定义小部件类包?

但是,我希望在与我致电uic.loadUi的位置相同的文件中定义自定义窗口小部件的类。我试图做到这一点,像这样:

class MyCustomClass(QtWidgets.QPushButton): 
    """ This is my custom class for my custom widget """ 
    def __init__(self, *args): 
     QtWidgets.QPushButton.__init__(self, *args) 

... 

sys.modules['mycustompackage'] = MyCustomClass 
uic.loadUi('my_ui.ui', self, 'mycustompackage') # Loads .ui file which contains the MyCustomWidget widget 

然而,这将返回以下错误:

AttributeError: type object 'MyCustomClass' has no attribute 'MyCustomWidget' 

有什么我可以做,使这个实际工作?我怀疑MyCustomClass没有按照uic.loadUi的方式定义。

在Qt Designer中,我已经晋升MyCustomWidget

<?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="QWidget" name="centralwidget"> 
    <widget class="MyCustomWidget" name="customWidget"> 
    <property name="geometry"> 
    <rect> 
     <x>50</x> 
     <y>70</y> 
     <width>113</width> 
     <height>32</height> 
    </rect> 
    </property> 
    <property name="text"> 
    <string>PushButton</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>MyCustomWidget</class> 
    <extends>QPushButton</extends> 
    <header>MyCustomClass</header> 
    </customwidget> 
</customwidgets> 
<resources/> 
<connections/> 
</ui> 

解决方案

我解决它使用上述的.ui文件是这样的:

class MyCustomClasses(object): 
    class MyCustomWidget(QtWidgets.QPushButton): 
     def __init__(self, *args): 
      QtWidgets.QPushButton.__init__(self, *args) 

... 

sys.modules['MyCustomClasses'] = MyCustomClasses 
uic.loadUi('my_ui.ui', self) # Loads .ui file which contains MyCustomWidget 

回答

0

引述从您链接到的文档中,loadUi的第三个参数是:

the optional package that is the base package for any relative imports of custom widgets [emphasis added]

定制类将从中导入的实际模块名必须在ui文件本身中指定。在Qt Designer中,这是通过将“头文件”设置为适当的值来实现的,它将存储在ui文件中的<header>标记中。请注意,此值可以是模块的完全限定包路径(例如“pkg.mymodule”) - 在这种情况下,不需要使用loadUi的第三个参数。不应该有任何需要sys.module黑客。

loadUi功能很简单。它只是以与命令行工具完全相同的方式生成一个python模块,然后使用exec加载它。