pip install PyQt6 pyqt6-tools
或者
pip install PySide6
假设你的自定义控件时from vtk.test2.testhead import testfaQ
首先拉一个QWidget
右键Promote to…
在header file里写上 vtk.test2.testhead(写vtk/test2/testhead.h或者vtk/test2/testhead或者vtk.test2.testhead.h都是可以的)
在promoted class name里写testfaQ
然后点Add,最后Promote
最后pyuic/pyside6-uic
可以看到最后那一句就是from vtk.test2.testhead import testfaQ
就实现了自定义控件了
miniconda3/envs/qt_test/lib/python3.8/site-packages/PyQt6/uic/uiparser.py
其中header指promoted widgets里的Headfile,
classname指的是promoted widgets里的promoted class name
可以看出来
foo/bar/baz.h->foo.bar.baz
foo.bar.baz.h->foo.bar.baz
foo.bar.baz->foo.bar.baz
class UIParser(object):
def _handle_custom_widgets(self, el):
""" Handle the element. """
def header2module(header):
"""header2module(header) -> string
Convert paths to C++ header files to according Python modules
>>> header2module("foo/bar/baz.h")
'foo.bar.baz'
"""
if header.endswith(".h"):
header = header[:-2]
mpath = []
for part in header.split('/'):
# Ignore any empty parts or those that refer to the current
# directory.
if part not in ('', '.'):
if part == '..':
# We should allow this for Python3.
raise SyntaxError("custom widget header file name may not contain '..'.")
mpath.append(part)
return '.'.join(mpath)
for custom_widget in el:
classname = custom_widget.findtext("class")
self.factory.addCustomWidget(classname,
custom_widget.findtext("extends") or "QWidget",
header2module(custom_widget.findtext("header")))
miniconda3/envs/qt_test/lib/python3.8/site-packages/PyQt6/uic/Compiler/qobjectcreator.py
addCustomWidget对应着上面的addCustomWidget
widgetClass指的是promoted widgets里的promoted class name
module指promoted widgets里的Headfile
最后会调用_writeImportCode,
得到from module import widgetClass
class _CustomWidgetLoader(object):
def __init__(self):
self._widgets = {}
self._usedWidgets = set()
def addCustomWidget(self, widgetClass, baseClass, module):
assert widgetClass not in self._widgets
self._widgets[widgetClass] = (baseClass, module)
def _writeImportCode(self):
imports = {}
for widget in self._usedWidgets:
_, module = self._widgets[widget]
imports.setdefault(module, []).append(widget)
for module, classes in sorted(imports.items()):
write_code("from %s import %s" % (module, ", ".join(sorted(classes))))
ui的写法与uic里一样
然后用QUiLoader()的load加载ui
如果你是pyside,一定要写registerCustomWidget将对应的类加载进来
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import os
from PySide6 import QtCore
from PySide6.QtUiTools import QUiLoader
from PySide6.QtWidgets import QApplication
from pyqtgraph import PlotWidget
os.environ["PYSIDE_DESIGNER_PLUGINS"] = "."
class Stock:
def __init__(self):
loader = QUiLoader()
loader.registerCustomWidget(PlotWidget)
self.ui = loader.load('my_mainwindow.ui')
hour = list(range(1, 11))
temperature = [30, 32, 34, 32, 33, 31, 29, 32, 35, 45]
self.ui.graphWidget.plot(hour, temperature)
if __name__ == '__main__':
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_ShareOpenGLContexts)
app = QApplication([])
stock = Stock()
stock.ui.show()
# window = MainWindow()
# window.show()
app.exec()
参考:
https://www.pythonguis.com/tutorials/pyqt6-embed-pyqtgraph-custom-widgets-qt-app/
https://doc.qt.io/qtforpython/PySide6/QtUiTools/QUiLoader.html#PySide6.QtUiTools.PySide6.QtUiTools.QUiLoader.registerCustomWidget
https://stackoverflow.com/questions/68528717/environment-variable-pyside-designer-plugins-is-not-set-bailing-out
https://doc-snapshots.qt.io/qtforpython-dev/tutorials/basictutorial/uifiles.html#custom-widgets-in-qt-designer
https://blog.csdn.net/feiyangqingyun/article/details/123005373
https://blog.csdn.net/panchang199266/article/details/104249647