我正在寻找一种在Qt Designer中使用Qt for Python(PySide2)编写的自定义小部件的有效使用方法。
我发现,可以使用基本窗口小部件设计GUI,然后将类换出到UI文件中的自定义窗口小部件,并向QUiLoader
告知子类loader.registerCustomWidget(MyMainWindow)
,但随后在Qt Designer中再次打开它效果不佳。
我读过this similar question for 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无法正确放置三个标签。
答案 0 :(得分:2)
在Qt Designer中使用自定义窗口小部件的主要方法有两种:
这是最简单,最省力的方式,如果是内部窗口小部件,则只需右键单击该窗口小部件并选择 Promote To ... ,然后输入:
以上内容所产生的是以下内容:
...
<widget class="RadialBar" name="widget" native="true"/>
...
<customwidgets>
<customwidget>
<class>RadialBar</class>
<extends>QWidget</extends>
<header>radialbar.h</header>
<container>1</container>
</customwidget>
</customwidgets>
...
也就是说,更改类,并在 customwidget 中添加一个指向该类名称的字段:<class> NAME_OF_CLASS </class>
,它们继承的类名称<extends>CLASS_EXTENDS</extends>
和文件路径将文件扩展名从.py更改为.h <header>PATH_OF_FILE.h</header>
,即与您输入表单相同的数据。
对于根窗口小部件,它无法通过Qt Designer完成,但是我看到您已经理解了逻辑但没有正确修改所有内容,主要错误是指出它们继承的类< / p>
<customwidgets>
<customwidget>
<class>MyMainWindow</class>
<extends>QMainWindow</extends> <----
<header>mymainwindow.h</header>
<container>1</container>
</customwidget>
</customwidgets>
因此正确的文件是:
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>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>
mymainwindow.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_())