HoO*_*man 5 python pyqt qml pyqt5
我想在Qml中显示一个矩形,我想从我的python代码中更改矩形的属性(宽度,长度).实际上,python代码中有一个套接字连接,通过该连接从另一台计算机接收宽度和长度的值.简单来说:另一个用户应该能够实时调整这个矩形.我知道如何在我的python文件中使用PyQt5建立套接字连接,我可以从python中显示qml文件.
但是,我很难通过我的python代码访问矩形的参数.我怎样才能做到这一点?
这是我的qml文件的简化示例:
import QtQuick 2.11
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: Screen.width/2
height: Screen.height/2
Rectangle {
id: rectangle
x: 187
y: 92
width: 200
height: 200
color: "blue"
}
}
Run Code Online (Sandbox Code Playgroud)
这是我在.py文件中写的内容:
from PyQt5.QtQml import QQmlApplicationEngine, QQmlProperty
from PyQt5.QtQuick import QQuickWindow, QQuickView
from PyQt5.QtCore import QObject, QUrl
from PyQt5.QtWidgets import QApplication
import sys
def run():
myApp = QApplication(sys.argv)
myEngine = QQmlApplicationEngine()
myEngine.load('mainViewofHoomanApp.qml')
if not myEngine.rootObjects():
return -1
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
Run Code Online (Sandbox Code Playgroud)
eyl*_*esc 13
有几种方法可以从 python/C++ 修改 QML 元素的属性,每种方法都有其优点和缺点。
setProperty()或property()分别或QQmlProperty。
main.qml(qml用于接下来的 2 .py)
import QtQuick 2.11
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: Screen.width/2
height: Screen.height/2
Rectangle {
id: rectangle
x: 187
y: 92
width: 200
height: 200
color: "blue"
objectName: "foo_object"
}
}
Run Code Online (Sandbox Code Playgroud)
import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
def testing(r):
import random
w = r.property("width")
h = r.property("height")
print("width: {}, height: {}".format(w, h))
r.setProperty("width", random.randint(100, 400))
r.setProperty("height", random.randint(100, 400))
def run():
myApp = QtGui.QGuiApplication(sys.argv)
myEngine = QtQml.QQmlApplicationEngine()
directory = os.path.dirname(os.path.abspath(__file__))
myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))
if not myEngine.rootObjects():
return -1
r = myEngine.rootObjects()[0].findChild(QtCore.QObject, "foo_object")
timer = QtCore.QTimer(interval=500)
timer.timeout.connect(partial(testing, r))
timer.start()
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
Run Code Online (Sandbox Code Playgroud)
import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
def testing(r):
import random
w_prop = QtQml.QQmlProperty(r, "width")
h_prop = QtQml.QQmlProperty(r, "height")
print("width: {}, height: {}".format(w_prop.read(), w_prop.read()))
w_prop.write(random.randint(100, 400))
h_prop.write(random.randint(100, 400))
def run():
myApp = QtGui.QGuiApplication(sys.argv)
myEngine = QtQml.QQmlApplicationEngine()
directory = os.path.dirname(os.path.abspath(__file__))
myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))
if not myEngine.rootObjects():
return -1
r = myEngine.rootObjects()[0].findChild(QtCore.QObject, "foo_object")
timer = QtCore.QTimer(interval=500)
timer.timeout.connect(partial(testing, r))
timer.start()
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
Run Code Online (Sandbox Code Playgroud)
这种方法的一个缺点是,如果对象与根对象的关系很复杂(有时在其他 QML 中的对象很难用 findChild 访问),访问对象的部分变得复杂,有时甚至不可能,因此该方法将失败。另一个问题是,当使用 objectName 作为主要搜索数据时,Python 层对 QML 层的依赖性很高,因为如果在 QML 中修改了 objectName,则必须修改 Python 中的逻辑。另一个缺点是,通过不管理 QML 对象的生命周期,它可能会在 Python 不知道的情况下被消除,因此它会访问不正确的引用,从而导致应用程序意外终止。
主文件
import QtQuick 2.11
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
width: Screen.width/2
height: Screen.height/2
Rectangle {
id: rectangle
x: 187
y: 92
width: r_manager.width
height: r_manager.height
color: "blue"
}
}
Run Code Online (Sandbox Code Playgroud)
主文件
import os
import sys
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
class RectangleManager(QtCore.QObject):
widthChanged = QtCore.pyqtSignal(float)
heightChanged = QtCore.pyqtSignal(float)
def __init__(self, parent=None):
super(RectangleManager, self).__init__(parent)
self._width = 100
self._height = 100
@QtCore.pyqtProperty(float, notify=widthChanged)
def width(self):
return self._width
@width.setter
def width(self, w):
if self._width != w:
self._width = w
self.widthChanged.emit(w)
@QtCore.pyqtProperty(float, notify=heightChanged)
def height(self):
return self._height
@height.setter
def height(self, h):
if self._height != h:
self._height = h
self.heightChanged.emit(h)
def testing(r):
import random
print("width: {}, height: {}".format(r.width, r.height))
r.width = random.randint(100, 400)
r.height = random.randint(100, 400)
def run():
myApp = QtGui.QGuiApplication(sys.argv)
myEngine = QtQml.QQmlApplicationEngine()
manager = RectangleManager()
myEngine.rootContext().setContextProperty("r_manager", manager)
directory = os.path.dirname(os.path.abspath(__file__))
myEngine.load(QtCore.QUrl.fromLocalFile(os.path.join(directory, 'main.qml')))
if not myEngine.rootObjects():
return -1
timer = QtCore.QTimer(interval=500)
timer.timeout.connect(partial(testing, manager))
timer.start()
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
Run Code Online (Sandbox Code Playgroud)
缺点是您必须编写更多代码。优点是对象可以被所有 QML 访问,因为它使用了 setContextProperty,另一个优点是如果 QML 对象被删除,它不会产生问题,因为只消除了绑定。最后,通过不使用 objectName,依赖项不存在。
所以我更喜欢使用第二种方法,更多信息请阅读Interacting with QML from C++。
| 归档时间: |
|
| 查看次数: |
698 次 |
| 最近记录: |