【问题标题】:Calling custom class in .ui file fails在 .ui 文件中调用自定义类失败
【发布时间】:2012-10-30 19:01:32
【问题描述】:

当我尝试从 .ui 文件中引用我的自定义类时出现此错误。我做的有什么问题?

"QFormBuilder was unable to create a custom widget of the class 'TimelinePane'; defaulting to base class 'QWidget'." 

QWidget 弹出我在.ui 文件中指定的布局。问题只是自定义类。

为了添加自定义类的描述,我手动修改了.ui 文件(添加了整个<customwidgets> 部分),这就是为什么我必须打开一个新问题,因为我还没有找到相同的 Q。我怀疑.ui 文件中类的路径,但我尝试的所有选项(请参阅我注释掉的部分)都不起作用。我也猜想使用python 不应该是这里的问题,但我并不完全确定。还没试过C++

from PySide import QtGui  
from PySide import QtCore
from PySide import QtUiTools

class MyWidget(QtGui.QMainWindow):
    def __init__(self, *args):  
       apply(QtGui.QMainWindow.__init__, (self,) + args)

       loader = QtUiTools.QUiLoader()
       file = QtCore.QFile('./src/prove_qt_ui_file/prove_main_widget.ui') 
       file.open(QtCore.QFile.ReadOnly)
       self.myWidget = loader.load(file, self)
       file.close()
       self.setCentralWidget(self.myWidget)

if __name__ == '__main__':  
   import sys  
   import os
   print("Running in " + os.getcwd() + " .\n")
   app = QtGui.QApplication(sys.argv)  
   win  = MyWidget()  
   win.show()
   app.exec_()

prove_main_widget.ui

<?xml version="1.0" encoding="UTF-8" ?>
<ui version="4.0">
 <class>MyWidget</class>
 <widget class="QWidget" name="MyWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>687</width>
    <height>698</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Runtime Monitor</string>
  </property>
  <layout class="QVBoxLayout">
   <property name="spacing">
    <number>0</number>
   </property>
   <property name="margin">
    <number>0</number>
   </property>
   <item>
    <widget class="QSplitter" name="splitter">
     <property name="orientation">
      <enum>Qt::Vertical</enum>
     </property>
     <property name="handleWidth">
      <number>9</number>
     </property>
     <widget class="QTreeWidget" name="warn_tree">
      <attribute name="headerVisible">
       <bool>false</bool>
      </attribute>
      <column>
       <property name="text">
        <string notr="true">1</string>
       </property>
      </column>
     </widget>
     <widget class="QTreeWidget" name="tree_all_devices">
      <attribute name="headerVisible">
       <bool>false</bool>
      </attribute>
      <column>
       <property name="text">
        <string notr="true">1</string>
       </property>
      </column>
     </widget>
     <widget class="TimelinePane" name="timeline_pane" native="true">
      <property name="minimumSize">
       <size>
        <width>0</width>
        <height>80</height>
       </size>
      </property>
      <property name="whatsThis">
       <string extracomment="Timeline"/>
      </property>
     </widget>
    </widget>
   </item>
  </layout>
 </widget>
 <customwidgets>
  <customwidget>
   <class>TimelinePane</class>
   <extends>QWidget</extends>
<!--   <header>timeline_pane</header> --> <!-- NG -->
<!--   <header>prove_qt_ui_file.timeline_pane</header> --> <!-- NG -->
   <header>src.prove_qt_ui_file.timeline_pane</header>  <!-- NG -->
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

timeline_pane.py

from PySide.QtGui import QWidget, QGraphicsScene, QGraphicsView, QColor, QHBoxLayout, QPushButton
class TimelinePane(QWidget):
    def __init__(self, parent):
        super(TimelinePane, self).__init__()
        print '\tTimelinePane init 1' # This doesn't print.

(环境)Ubuntu 12.04,python 2.7.3

【问题讨论】:

  • 您必须为您的自定义小部件创建设计器插件才能使其与 QUiBuilder 一起使用

标签: python qt pyside qt-designer


【解决方案1】:

理论上,要让您的自定义小部件工作,您只需调用:

loader.registerCustomWidget(TimelinePane)

在调用 loader.load() 之前。您需要根据您的情况添加相关的导入语句:

from timeline_pane import TimelinePane

但是,我刚刚在 Ubuntu 12.04 x86_64 上使用 PySide 1.1.2 对此进行了测试,结果导致了段错误。 YMMV,所以请测试。

我最终实现了这个解决方法:http://www.mail-archive.com/pyside@qt-project.org/msg00306.html

简单来说就是重写QUiLoader的creteWidget()方法,如果widget的class_name不在self.availableWidgets()中,根据自己添加的customWidgets实例变量自行实例化。

顺便说一句,您也可以使用 Qt 设计器中的右键单击“Promote To”功能,而不是直接编辑 ui 文件。

【讨论】:

  • 这里有相同/类似的问题:虽然您的解决方法能够调出 gui,但仍然无法创建 customWidget:AttributeError: type object 'PySide.QtGui.QWidget' has no attribute 'customWidgets'。也许我使用了错误的基类?
  • 这意味着你创建了一个QUiLoader 的子类。在其 __init__ 函数中,您调用父级 init,但您也在 self 上设置了 customWidgets 字典(由调用者传入)。
  • 在 PySide2(在我的情况下为 5.15.2)中,只需在 loader.load 之前调用 loader.registerCustomWidget(TimelinePane) 就足够了。当然,TimelinePane 类必须已经导入。
  • @NikolaiSaiko 有一个赞成票,这解决了我与 pyqtgraph 和 .ui 文件有关的问题。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多