我正在寻找一种有效地使用Qt for Python(PySide2)中自定义小部件的方法。
我发现,可以使用基本小部件设计GUI,然后在UI文件中仅交换类以使用自定义小部件,并通知QUiLoader
子类loader.registerCustomWidget(MyMainWindow)
,但是在Qt Designer中再次打开它并不那么有效。
我在这个类似问题的PyQt方面的回答中读到,您必须为自定义小部件编写插件。 PySide2中是否也存在此可能性?
以下是一些示例代码:
custom_widget.py:
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_())
custom_widget_original.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>
custom_widget_modified.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无法正确放置这三个标签。
registerCustomWidget
中使用完全相同的类名,并且在 XML 的<widget>
定义中也使用完全相同的类名,那么<customwidgets/>
部分可以省略。 - karolyi