2016-08-05 72 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加載它。