Python中PyQt5与QML交互感觉比较繁琐,如何优化?
繁琐主要体现在:
1、Python 中不能使用 QML 中的 id 查找控件,需要用 objectName,,一般这两者值是完全一样的,重复劳动
ComboBox {
id: cmbPort
objectName: "cmbPort"
Layout.minimumWidth: 100 * 2 + 10 * 2 + lblSer.width
model: ports
}
2、pyqtProperty 不太好用,,搞了好久没用起来,放弃了
3、Python 中无法直接使用 QML 中的控件,必须用 findObject 在 Python 中再定义一遍
self.cmbPort = self.win.findChild(QObject, 'cmbPort')
self.cmbBaud = self.win.findChild(QObject, 'cmbBaud')
self.cmbData = self.win.findChild(QObject, 'cmbData')
self.cmbParity = self.win.findChild(QObject, 'cmbParity')
self.cmbStop = self.win.findChild(QObject, 'cmbStop')
self.txtMain = self.win.findChild(QObject, ‘txtMain’)
self.txtSend = self.win.findChild(QObject, ‘txtSend’)
self.chkRHex = self.win.findChild(QObject, ‘chkRHex’)
self.chkWave = self.win.findChild(QObject, ‘chkWave’)
self.chkTHex = self.win.findChild(QObject, ‘chkTHex’)
self.chkLine = self.win.findChild(QObject, ‘chkLine’)
self.chkTime = self.win.findChild(QObject, ‘chkTime’)
self.btnOpen = self.win.findChild(QObject, ‘btnOpen’)
4、Python 中不能直接访问 QML 控件的属性,而需要用 property、setProperty 间接访问
比如 CombBox 控件有 currentText 属性,不能用 self.cmbPort.currentText 访问,而必须用 self.cmbPort.property('currentText')访问
5、文档资料很少,,没有应用示例
代码在此:https://github.com/XIVN1987/QmlSer
运行效果:

Python中PyQt5与QML交互感觉比较繁琐,如何优化?
好几次想试试 QML,但还是觉得费劲,干脆就还是 designer 直接排了,省事还可视化
PyQt5里用QML确实容易搞出一堆信号槽的绑定代码,看着就头大。其实可以换个思路,用QQmlProperty或者直接暴露Python对象给QML来简化。
比如把Python对象注册成QML上下文属性,这样在QML里就能直接调它的方法和属性。下面是个完整例子:
import sys
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQml import QQmlApplicationEngine
class Backend(QObject):
def __init__(self):
super().__init__()
self._message = "Hello from Python"
@pyqtProperty(str)
def message(self):
return self._message
@pyqtSlot(str)
def update_message(self, text):
self._message = text
print(f"Message updated: {text}")
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
backend = Backend()
engine.rootContext().setContextProperty("backend", backend)
engine.load('main.qml') # QML文件里可以直接用backend对象
if not engine.rootObjects():
sys.exit(-1)
sys.exit(app.exec_())
对应的QML文件(main.qml):
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 400
height: 300
Text {
text: backend.message // 直接访问Python属性
anchors.centerIn: parent
}
Button {
text: "Click me"
onClicked: backend.update_message("New message from QML") // 直接调用Python方法
anchors.bottom: parent.bottom
}
}
这样就不用到处定义信号槽了,QML里直接操作Python对象,代码清爽很多。建议用上下文属性暴露核心对象。
是的,现在看来 Qt Widget 还是要比 Qt Quick 用起来更简单、快捷,,希望 Qt 官方的 Python 绑定能简化 Python 和 QML 的交互
不过 Widget 是给电脑桌面 GUI 设计的,没有考虑手机、平板等设备,,如果想开发手机应用的话可能还是得上 Qt Quick
PyQt 打包方便吗
挺简单,,“ pyinstaller -F xxx.py ”一条命令即可,,打包后最小 15M,也还能接受
lz 大佬,请教一下,我用 pyinstaller 打包后的 pyqt 应用在 win 下启动十分缓慢,要 40s 左右,运行倒挺流畅的。是什么参数配置不对吗?
打包速度很快,不到一分钟(我做的程序都比较小)
确实比直接运行.py 慢,,我自己用都是.py ,,只有给别人用的时候才打包
不过好像也没这么慢吧,,可能你的程序功能比较复杂吧,,
为什么要这么专业呢?随便写个 UI 就好了。。
感觉最大的硬伤是 QML 没有文档。
楼主你 github 这个 qml 我 qml.rootContext().setContextProperty(‘Ser’, QmlSer(qml.rootContext(), qml.rootObjects()[0])), 读取不到 rootObjects 啊

