Python 如何创建qml对象';"香港地产";“可动态更新”;通过插座连接?
我正在使用PyQt5和Qml创建客户机应用程序。这是我的Qml文件的简化示例:Python 如何创建qml对象';"香港地产";“可动态更新”;通过插座连接?,python,sockets,pyqt,qml,real-time,Python,Sockets,Pyqt,Qml,Real Time,我正在使用PyQt5和Qml创建客户机应用程序。这是我的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
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"
}
}
客户端应用程序必须从服务器接收上述矩形的属性。为此,我在“.py”文件中实现了一个套接字连接。client.py文件应该从服务器实时接收信息。我的灵感来自聊天应用程序,我使用(while True:{})循环来实现这一点:
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, socket
def run():
myApp = QApplication(sys.argv)
myEngine = QQmlApplicationEngine()
myEngine.load('mainViewofHoomanApp.qml')
Win = myEngine.rootObjects()[0]
rect = Win.findChild(QObject, "rectangle")
rect.setProperty("height", 10) # Here I am accessing the properties of the rectangle
if not myEngine.rootObjects():
return -1
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
它是套接字连接的格式:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Server_IPAddress = '192.168.1.163'
Port = 5000
client_socket.connect((Server_IPAddress,Port))
while True:
message = client_socket.recv(1024)
# Then the code extracts the parameters from the message
# and converts it to integer, and saves it in realT_width variable:
rect.setProperty("height", realT_width variable)
我对如何将这两个代码合并在一起感到困惑。如果我在写入myApp.exec_389;()命令后调用套接字连接,那么QML文件将不再对参数更改命令作出反应。另一方面,如果我在QML执行之前写入套接字连接,那么while循环将不允许执行后面的代码行。阻塞任务必须在另一个线程中执行,以便它们不会冻结GUI,在这种情况下,我将假定下一个是服务器,因此您必须首先启动它 server.py
import socket
import time
import random
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
v = random.randint(10, 100)
conn.sendall(str(v).encode())
time.sleep(1.)
import os
import sys
import threading
import socket
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
class SocketWorker(QtCore.QObject):
heightChanged = QtCore.pyqtSignal(float)
@QtCore.pyqtSlot()
def process(self):
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
data = s.recv(1024)
print('Received', repr(data))
try:
height = float(data)
self.heightChanged.emit(height)
except ValueError:
print("error")
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
def getWidth(self):
return self._width
def setWidth(self, w):
if self._width != w:
self._width = w
self.widthChanged.emit(w)
def getHeight(self):
return self._height
def setHeight(self, h):
if self._height != h:
self._height = h
self.heightChanged.emit(h)
width = QtCore.pyqtProperty(float, fget=getWidth, fset=setWidth, notify=widthChanged)
height = QtCore.pyqtProperty(float, fget=getHeight, fset=setHeight, notify=heightChanged)
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
worker = SocketWorker()
threading.Thread(target=worker.process, daemon=True).start()
worker.heightChanged.connect(manager.setHeight)
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
因此,我将创建一个QObject,在这里我可以创建信号,将在辅助线程上运行的套接字获得的信息发送给我发布的处理程序
client.py
import socket
import time
import random
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
v = random.randint(10, 100)
conn.sendall(str(v).encode())
time.sleep(1.)
import os
import sys
import threading
import socket
from PyQt5 import QtCore, QtGui, QtQml
from functools import partial
class SocketWorker(QtCore.QObject):
heightChanged = QtCore.pyqtSignal(float)
@QtCore.pyqtSlot()
def process(self):
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 65432 # The port used by the server
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
data = s.recv(1024)
print('Received', repr(data))
try:
height = float(data)
self.heightChanged.emit(height)
except ValueError:
print("error")
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
def getWidth(self):
return self._width
def setWidth(self, w):
if self._width != w:
self._width = w
self.widthChanged.emit(w)
def getHeight(self):
return self._height
def setHeight(self, h):
if self._height != h:
self._height = h
self.heightChanged.emit(h)
width = QtCore.pyqtProperty(float, fget=getWidth, fset=setWidth, notify=widthChanged)
height = QtCore.pyqtProperty(float, fget=getHeight, fset=setHeight, notify=heightChanged)
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
worker = SocketWorker()
threading.Thread(target=worker.process, daemon=True).start()
worker.heightChanged.connect(manager.setHeight)
return myApp.exec_()
if __name__ == "__main__":
sys.exit(run())
main.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: r_manager.width
height: r_manager.height
color: "blue"
}
}
显示您的服务器代码服务器代码是用Csharp编写的,很遗憾,我没有访问权限。但它会发送一个包含所需参数值的字符串。好的,我将发布一个简单的服务器代码来测试我的代码。谢谢你@Eylansec。它们运行时没有任何错误,客户端控制台打印字符串。但是,我想知道为什么它不显示图形窗口。可能它对myApp.exec_389;()命令没有反应?从服务器发送的随机数唯一的修改是我将主机变量更改为:HOST=socket.gethostname()Aha。对不起,我失礼了。我没有修改qml代码。