代码之家  ›  专栏  ›  技术社区  ›  Michael K.

在Qt设计器中使用自定义PySide2小部件

  •  1
  • Michael K.  · 技术社区  · 7 年前

    我正在寻找一种有效地使用Qt-Designer中用Qt-for-Python(PySide2)编写的自定义小部件的方法。

    QUiLoader 关于子类 loader.registerCustomWidget(MyMainWindow) ,但是在Qt Designer中再次打开它并不能很好地工作。

    我读了进去 this similar question for PyQt

    一些示例代码:

    import sys
    
    from PySide2.QtUiTools import QUiLoader
    from PySide2.QtWidgets import QApplication, QMainWindow, QAction, QMessageBox, QFileDialog, QTextBrowser
    from PySide2.QtCore import QFile
    
    
    class MyMainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setWindowTitle("Demo QtWidget App")
    
        def closeEvent(self, event):
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Quit?")
            msgBox.setText("Exit application?")
            msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            msgBox.setDefaultButton(QMessageBox.No)
            ret = msgBox.exec_()
            if ret == QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()
    
    
    if __name__ == '__main__':
        app = QApplication([])
        file = QFile("custom_widget_original.ui")
        #file = QFile("custom_widget_modified.ui")
        file.open(QFile.ReadOnly)
        loader = QUiLoader()
        loader.registerCustomWidget(MyMainWindow)
        main_window = loader.load(file)
        main_window.show()
        sys.exit(app.exec_())
    

    自定义\u小部件_原始.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="QWidget" name="centralwidget">
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="2">
         <widget class="QLabel" name="label">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QLabel" name="label_3">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>800</width>
         <height>21</height>
        </rect>
       </property>
       <widget class="QMenu" name="menuFile">
        <property name="title">
         <string>File</string>
        </property>
        <addaction name="actionExit"/>
       </widget>
       <addaction name="menuFile"/>
      </widget>
      <widget class="QStatusBar" name="statusbar"/>
      <action name="actionExit">
       <property name="text">
        <string>Exit</string>
       </property>
      </action>
     </widget>
     <resources/>
     <connections>
      <connection>
       <sender>actionExit</sender>
       <signal>triggered()</signal>
       <receiver>MainWindow</receiver>
       <slot>close()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>-1</x>
         <y>-1</y>
        </hint>
        <hint type="destinationlabel">
         <x>399</x>
         <y>299</y>
        </hint>
       </hints>
      </connection>
     </connections>
    </ui>
    

    这个版本会问你是否真的想退出。

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="MyMainWindow" 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">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>155</width>
         <height>15</height>
        </rect>
       </property>
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="2">
         <widget class="QLabel" name="label">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QLabel" name="label_3">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>800</width>
         <height>21</height>
        </rect>
       </property>
       <widget class="QMenu" name="menuFile">
        <property name="title">
         <string>File</string>
        </property>
        <addaction name="actionExit"/>
       </widget>
       <addaction name="menuFile"/>
      </widget>
      <widget class="QStatusBar" name="statusbar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>3</width>
         <height>18</height>
        </rect>
       </property>
      </widget>
      <action name="actionExit">
       <property name="text">
        <string>Exit</string>
       </property>
      </action>
     </widget>
     <customwidgets>
      <customwidget>
       <class>MyMainWindow</class>
       <extends>QWidget</extends>
       <header>mymainwindow.h</header>
       <container>1</container>
      </customwidget>
     </customwidgets>
     <resources/>
     <connections>
      <connection>
       <sender>actionExit</sender>
       <signal>triggered()</signal>
       <receiver>MainWindow</receiver>
       <slot>close()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>-1</x>
         <y>-1</y>
        </hint>
        <hint type="destinationlabel">
         <x>399</x>
         <y>299</y>
        </hint>
       </hints>
      </connection>
     </connections>
    </ui>
    

    这个 <customwidgets> 段在再次打开后由Qt Designer添加。

    修改后,Qt Designer没有正确放置三个标签。

    1 回复  |  直到 7 年前
        1
  •  5
  •   eyllanesc    7 年前

    在Qt设计器中使用自定义小部件有两种主要方法:

    1升级小部件:

    这是最简单、最省力的方法,如果是内部小部件,只需右键单击小部件并选择 提升到。。。 ,然后在:

    • 基类名称选择从中继承的类
    • 头文件放置文件的路径,将扩展名.py改为.h

    enter image description here

    ...
        <widget class="RadialBar" name="widget" native="true"/>
    ...
     <customwidgets>
      <customwidget>
       <class>RadialBar</class>
       <extends>QWidget</extends>
       <header>radialbar.h</header>
       <container>1</container>
      </customwidget>
     </customwidgets>
    ...
    

    也就是说,更改类,并在 自定义小部件 指向类的名称: <class> NAME_OF_CLASS </class> <extends>CLASS_EXTENDS</extends> 和文件路径将文件扩展名从.py更改为.h <header>PATH_OF_FILE.h</header> ,即与您输入表单的数据相同。

    在根小部件的情况下,它不能通过Qt设计器完成,但是我看到您已经理解了逻辑,但是您没有正确地修改所有内容,您的主要错误是指出了它们继承的类

     <customwidgets>
      <customwidget>
       <class>MyMainWindow</class>
       <extends>QMainWindow</extends> <----
       <header>mymainwindow.h</header>
       <container>1</container>
      </customwidget>
     </customwidgets>
    

    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>MainWindow</class>
     <widget class="MyMainWindow" 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">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>155</width>
         <height>15</height>
        </rect>
       </property>
       <layout class="QGridLayout" name="gridLayout">
        <item row="0" column="0">
         <widget class="QLabel" name="label_2">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="2">
         <widget class="QLabel" name="label">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
        <item row="0" column="1">
         <widget class="QLabel" name="label_3">
          <property name="text">
           <string>TextLabel</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
      <widget class="QMenuBar" name="menubar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>800</width>
         <height>21</height>
        </rect>
       </property>
       <widget class="QMenu" name="menuFile">
        <property name="title">
         <string>File</string>
        </property>
        <addaction name="actionExit"/>
       </widget>
       <addaction name="menuFile"/>
      </widget>
      <widget class="QStatusBar" name="statusbar">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>0</y>
         <width>3</width>
         <height>18</height>
        </rect>
       </property>
      </widget>
      <action name="actionExit">
       <property name="text">
        <string>Exit</string>
       </property>
      </action>
     </widget>
     <customwidgets>
      <customwidget>
       <class>MyMainWindow</class>
       <extends>QMainWindow</extends>
       <header>mymainwindow.h</header>
       <container>1</container>
      </customwidget>
     </customwidgets>
     <resources/>
     <connections>
      <connection>
       <sender>actionExit</sender>
       <signal>triggered()</signal>
       <receiver>MainWindow</receiver>
       <slot>close()</slot>
       <hints>
        <hint type="sourcelabel">
         <x>-1</x>
         <y>-1</y>
        </hint>
        <hint type="destinationlabel">
         <x>399</x>
         <y>299</y>
        </hint>
       </hints>
      </connection>
     </connections>
    </ui>
    

    MyMain窗口.py

    import sys
    
    from PySide2.QtUiTools import QUiLoader
    from PySide2.QtWidgets import QApplication, QMainWindow, QMessageBox
    from PySide2.QtCore import QFile
    
    
    class MyMainWindow(QMainWindow):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.setWindowTitle("Demo QtWidget App")
    
        def closeEvent(self, event):
            msgBox = QMessageBox()
            msgBox.setWindowTitle("Quit?")
            msgBox.setText("Exit application?")
            msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            msgBox.setDefaultButton(QMessageBox.No)
            ret = msgBox.exec_()
            if ret == QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()
    
    
    if __name__ == '__main__':
        app = QApplication([])
        file = QFile("custom_widget_modified.ui")
        file.open(QFile.ReadOnly)
        loader = QUiLoader()
        loader.registerCustomWidget(MyMainWindow)
        main_window = loader.load(file)
        main_window.show()
        sys.exit(app.exec_())
    

    2升级小部件:

    推荐文章