最终实现效果:(左边是一个web界面,右边是qt的doubleSpinBox和pushButton)
我的思路是这样的:
首先建立一个flask Sever 用来接收qt提交的数据并保存在服务器中
然后web前端轮询的获取储存在服务器中的数据
(虽然知道轮询方式缺点巨大,但还没有想到好的办法,还请路过的大佬指点)
项目文件夹:
flask:
- from flask import Flask,render_template,url_for,request,jsonify
-
- # template_folder:模板的位置,
- # static_folder:静态文件放的位置(图片/css..),默认叫static
- # static_url_path:前端寻找静态文件的前缀, 默认叫/static g跟静态文件夹存放的位置名称,不一样
- app = Flask(__name__ ,template_folder = 'templates', static_folder='static', static_url_path='/static')
-
-
- @app.route("/index",methods=['GET']) # 设置路由,允许GET请求
- def showIndexHtml():
- return render_template("test.html")
-
- @app.route("/postData",methods=['POST'])
- def postDataformUI():
- global data
- data = request.get_json()
- return jsonify(msg="ok")
-
- @app.route("/getData",methods=['GET'])
- def getDataformFlask():
- doubleSpinBoxValue = data["doubleSpinBoxValue"]
- return jsonify(doubleSpinBoxValue=doubleSpinBoxValue)
-
- app.run(host="0.0.0.0")
前端:
- HTML>
- <html>
- <head>
- <meta charset="utf-8">
- <title>websocket通信客户端title>
- <script src="https://cdn.staticfile.org/echarts/4.3.0/echarts.min.js">script>
- <script src="https://code.jquery.com/jquery-3.6.0.min.js">script>
-
- head>
-
- <body>
- <div id="main" style="width: 100%; height:100%; position: absolute;">div>
- <script>
- function getNum(url,callback) {
- var xmlhttp=new XMLHttpRequest();
- // var url="http://127.0.0.1:5000/getData";
- var type="GET";//方法
- var doubleSpinBoxValue = 0;
- xmlhttp.open(type,url,true);//方法,接口,异步
- xmlhttp.send();//发送请求
- xmlhttp.onreadystatechange=function(){
- if(xmlhttp.status==200&&xmlhttp.readyState==4){
- var result=JSON.parse(xmlhttp.response);
- doubleSpinBoxValue = result.doubleSpinBoxValue;
- callback(doubleSpinBoxValue);
- console.log(doubleSpinBoxValue, typeof doubleSpinBoxValue)//result即为接口返回给我们的数据具体进行处理可以封装一个方法
- }
- };
- }
-
- function html(){
- //在此希望调用获取年龄方法得到小明的年龄
- let num=getNum("http://127.0.0.1:5000/getData", function(doubleSpinBoxValue){
- var myChart = echarts.init(document.getElementById('main'));
- let angle = 0; //角度,用来做简单的动画效果的
- let value = doubleSpinBoxValue;
- console.log(doubleSpinBoxValue, typeof doubleSpinBoxValue);
- option = {
- backgroundColor: "#061740",
- title: {
- text: "{a|" + value + "}{c|%}",
- x: "center",
- y: "center",
- textStyle: {
- rich: {
- a: {
- fontSize: 48,
- color: "#29EEF3",
- },
-
- c: {
- fontSize: 20,
- color: "#ffffff",
- // padding: [5,0]
- },
- },
- },
- },
- legend: {
- type: "plain",
- orient: "vertical",
- right: 0,
- top: "10%",
- align: "auto",
- data: [
- {
- name: "涨价后没吃过",
- icon: "circle",
- },
- {
- name: "天天吃",
- icon: "circle",
- },
- {
- name: "三五天吃一次",
- icon: "circle",
- },
- {
- name: "半个月吃一次",
- icon: "circle",
- },
- ],
- textStyle: {
- color: "white",
- fontSize: 16,
- padding: [10, 1, 10, 0],
- },
- selectedMode: false,
- },
- series: [
- {
- name: "ring5",
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- return {
- type: "arc",
- shape: {
- cx: api.getWidth() / 2,
- cy: api.getHeight() / 2,
- r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
- startAngle: ((0 + angle) * Math.PI) / 180,
- endAngle: ((90 + angle) * Math.PI) / 180,
- },
- style: {
- stroke: "#0CD3DB",
- fill: "transparent",
- lineWidth: 1.5,
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "ring5",
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- return {
- type: "arc",
- shape: {
- cx: api.getWidth() / 2,
- cy: api.getHeight() / 2,
- r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
- startAngle: ((180 + angle) * Math.PI) / 180,
- endAngle: ((270 + angle) * Math.PI) / 180,
- },
- style: {
- stroke: "#0CD3DB",
- fill: "transparent",
- lineWidth: 1.5,
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "ring5",
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- return {
- type: "arc",
- shape: {
- cx: api.getWidth() / 2,
- cy: api.getHeight() / 2,
- r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
- startAngle: ((270 + -angle) * Math.PI) / 180,
- endAngle: ((40 + -angle) * Math.PI) / 180,
- },
- style: {
- stroke: "#0CD3DB",
- fill: "transparent",
- lineWidth: 1.5,
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "ring5",
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- return {
- type: "arc",
- shape: {
- cx: api.getWidth() / 2,
- cy: api.getHeight() / 2,
- r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
- startAngle: ((90 + -angle) * Math.PI) / 180,
- endAngle: ((220 + -angle) * Math.PI) / 180,
- },
- style: {
- stroke: "#0CD3DB",
- fill: "transparent",
- lineWidth: 1.5,
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "ring5",
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- let x0 = api.getWidth() / 2;
- let y0 = api.getHeight() / 2;
- let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65;
- let point = getCirlPoint(x0, y0, r, 90 + -angle);
- return {
- type: "circle",
- shape: {
- cx: point.x,
- cy: point.y,
- r: 4,
- },
- style: {
- stroke: "#0CD3DB", //粉
- fill: "#0CD3DB",
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "ring5", //绿点
- type: "custom",
- coordinateSystem: "none",
- renderItem: function (params, api) {
- let x0 = api.getWidth() / 2;
- let y0 = api.getHeight() / 2;
- let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65;
- let point = getCirlPoint(x0, y0, r, 270 + -angle);
- return {
- type: "circle",
- shape: {
- cx: point.x,
- cy: point.y,
- r: 4,
- },
- style: {
- stroke: "#0CD3DB", //绿
- fill: "#0CD3DB",
- },
- silent: true,
- };
- },
- data: [0],
- },
- {
- name: "吃猪肉频率",
- type: "pie",
- radius: ["58%", "45%"],
- silent: true,
- clockwise: true,
- startAngle: 90,
- z: 0,
- zlevel: 0,
- label: {
- normal: {
- position: "center",
- },
- },
- data: [
- {
- value: value,
- name: "",
- itemStyle: {
- normal: {
- color: {
- // 完成的圆环的颜色
- colorStops: [
- {
- offset: 0,
- color: "#4FADFD", // 0% 处的颜色
- },
- {
- offset: 1,
- color: "#28E8FA", // 100% 处的颜色
- },
- ],
- },
- },
- },
- },
- {
- value: 100 - value,
- name: "",
- label: {
- normal: {
- show: false,
- },
- },
- itemStyle: {
- normal: {
- color: "#173164",
- },
- },
- },
- ],
- },
-
- {
- name: "",
- type: "gauge",
- radius: "58%",
- center: ["50%", "50%"],
- startAngle: 0,
- endAngle: 359.9,
- splitNumber: 8,
- hoverAnimation: true,
- axisTick: {
- show: false,
- },
- splitLine: {
- length: 60,
- lineStyle: {
- width: 5,
- color: "#061740",
- },
- },
- axisLabel: {
- show: false,
- },
- pointer: {
- show: false,
- },
- axisLine: {
- lineStyle: {
- opacity: 0,
- },
- },
- detail: {
- show: false,
- },
- data: [
- {
- value: 0,
- name: "",
- },
- ],
- },
- ],
- };
-
- myChart.setOption(option);
-
- //获取圆上面某点的坐标(x0,y0表示坐标,r半径,angle角度)
- function getCirlPoint(x0, y0, r, angle) {
- let x1 = x0 + r * Math.cos((angle * Math.PI) / 180);
- let y1 = y0 + r * Math.sin((angle * Math.PI) / 180);
- return {
- x: x1,
- y: y1,
- };
- }
-
- function draw() {
- angle = angle + 3;
- myChart.setOption(option, true);
- //window.requestAnimationFrame(draw);
- }
-
- setInterval(function () {
- //用setInterval做动画感觉有问题
- draw();
- }, 100);
- });
- }
-
- function funcTest(){
- //每隔3秒执行一次timelyFun方法
- window.setInterval("html()",3000);
- }
- window.onload = funcTest;
-
-
- script>
- body>
- html>
pyqt:
- from PyQt5.Qt import *
- from resource.home import Ui_MainWindow
- from PyQt5.QtCore import Qt
- from PyQt5 import QtCore,QtGui
- from PyQt5.QtWidgets import QApplication
- from PyQt5.QtWebEngineWidgets import *
- import sys,threading,requests,json
-
-
- class homePane(QMainWindow, Ui_MainWindow):
- def __init__(self, parent=None, *args, **kwargs):
- self.app = QApplication(sys.argv)
- super().__init__(parent, *args, **kwargs)
- self.setAttribute(Qt.WA_StyledBackground, True)
- self.setupUi(self)
- self.setWindowTitle("WEBTest")
- icon = QtGui.QIcon()
- icon.addPixmap(QtGui.QPixmap("resource/images/webIcon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.setWindowIcon(icon)
- self.setIconSize(QtCore.QSize(40, 40))
-
- # 设置按钮图标
- icon1 = QtGui.QIcon()
- icon1.addPixmap(QtGui.QPixmap("resource/images/保存.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
- self.pushButton.setIcon(icon1)
- self.pushButton.setIconSize(QtCore.QSize(30, 30))
-
- self.doubleSpinBox.setStyleSheet(
- "QAbstractSpinBox{background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 38, 200, 255), stop:1 rgba(255, 255, 255, 255));color: rgb(255, 255, 255);font: 16pt 'Arial';border-radius:8px;}"
- "QAbstractSpinBox::up-button{subcontrol-origin: padding;subcontrol-position: center right; border-image: url('resource/images/向右.png');width:40px;height:40px;}"
- "QAbstractSpinBox::down-button{subcontrol-origin: padding;subcontrol-position: center left;border-image: url('resource/images/向左.png');width:40px;height:40px;}"
- "QAbstractSpinBox::up-button:pressed{subcontrol-origin: padding;subcontrol-position: center right;background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 81, 200, 255), stop:1 rgba(255, 255, 255, 255));}"
- "QAbstractSpinBox::down-button:pressed{subcontrol-origin: padding;subcontrol-position: center left;background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 81, 200, 255), stop:1 rgba(255, 255, 255, 255));}"
- )
-
- self.browser = QWebEngineView()
- # 加载外部的web界面
- self.browser.load(QUrl('http://127.0.0.1:5000/index'))
- self.scrollArea.setWidget(self.browser)
-
-
- def saveNum(self):
- doubleSpinBoxValue = self.doubleSpinBox.value() # 获取doubleSpinBox的值
- postData = json.dumps({'doubleSpinBoxValue': doubleSpinBoxValue})
- headers = {"Content-type": "application/json", "Accept": "*/*"}
- r = requests.post("http://127.0.0.1:5000/postData", data=postData, headers=headers)
- print(r.text)
-
-
-
- if __name__ == '__main__':
- app = QApplication(sys.argv)
- window = homePane()
- window.show()
- sys.exit(app.exec())
UI(home.py)
- # -*- coding: utf-8 -*-
-
- # Form implementation generated from reading ui file 'home.ui'
- #
- # Created by: PyQt5 UI code generator 5.15.6
- #
- # WARNING: Any manual changes made to this file will be lost when pyuic5 is
- # run again. Do not edit this file unless you know what you are doing.
-
-
- from PyQt5 import QtCore, QtGui, QtWidgets
-
-
- class Ui_MainWindow(object):
- def setupUi(self, MainWindow):
- MainWindow.setObjectName("MainWindow")
- MainWindow.resize(818, 622)
- self.centralwidget = QtWidgets.QWidget(MainWindow)
- self.centralwidget.setObjectName("centralwidget")
- self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
- self.horizontalLayout.setObjectName("horizontalLayout")
- self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
- self.scrollArea.setStyleSheet("border:3px solid rgb(0, 0, 0);\n"
- "border-radius:8px;")
- self.scrollArea.setWidgetResizable(True)
- self.scrollArea.setObjectName("scrollArea")
- self.scrollAreaWidgetContents = QtWidgets.QWidget()
- self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 590, 553))
- self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
- self.scrollArea.setWidget(self.scrollAreaWidgetContents)
- self.horizontalLayout.addWidget(self.scrollArea)
- self.widget_2 = QtWidgets.QWidget(self.centralwidget)
- self.widget_2.setObjectName("widget_2")
- self.verticalLayout = QtWidgets.QVBoxLayout(self.widget_2)
- self.verticalLayout.setObjectName("verticalLayout")
- self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.widget_2)
- self.doubleSpinBox.setMinimumSize(QtCore.QSize(100, 40))
- self.doubleSpinBox.setStyleSheet("QAbstractSpinBox{\n"
- " background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 38, 200, 255), stop:1 rgba(255, 255, 255, 255));\n"
- " color: rgb(255, 255, 255);\n"
- " font: 16pt \"Arial\";\n"
- "border-radius:8px;\n"
- "}\n"
- "QAbstractSpinBox::up-button{\n"
- " subcontrol-origin: padding;\n"
- " subcontrol-position: center right;\n"
- " border-image: url(:/police_classifcation/images/向右.png);\n"
- "width:40px;\n"
- "height:40px;\n"
- "}\n"
- "QAbstractSpinBox::down-button{\n"
- " image: url(:/new/prefix1/picture/sl1.png);\n"
- " subcontrol-origin: padding;\n"
- " subcontrol-position: center left;\n"
- " border-image: url(:/police_classifcation/images/向左.png);\n"
- "width:40px;\n"
- "height:40px;\n"
- "}\n"
- "QAbstractSpinBox::up-button:pressed{\n"
- " subcontrol-origin: padding;\n"
- " subcontrol-position: center right;\n"
- " background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 81, 200, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "}\n"
- "QAbstractSpinBox::down-button:pressed{\n"
- " subcontrol-origin: padding;\n"
- " subcontrol-position: center left;\n"
- " background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 81, 200, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "}")
- self.doubleSpinBox.setMaximum(100.0)
- self.doubleSpinBox.setProperty("value", 90.0)
- self.doubleSpinBox.setObjectName("doubleSpinBox")
- self.verticalLayout.addWidget(self.doubleSpinBox)
- self.pushButton = QtWidgets.QPushButton(self.widget_2)
- self.pushButton.setMinimumSize(QtCore.QSize(100, 40))
- self.pushButton.setStyleSheet("QPushButton {\n"
- "background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(0, 38, 200, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "border-radius:8px;\n"
- "color:white;\n"
- "spacing:20px;\n"
- " font: 14pt \"楷体\";\n"
- "}\n"
- "QPushButton:hover {\n"
- " background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(147, 33, 250, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "}\n"
- "QPushButton:pressed {\n"
- "background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(250, 33, 80, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "}\n"
- "QPushButton:disabled{\n"
- " background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255));\n"
- "}")
- self.pushButton.setText("")
- self.pushButton.setObjectName("pushButton")
- self.verticalLayout.addWidget(self.pushButton)
- self.horizontalLayout.addWidget(self.widget_2)
- self.horizontalLayout.setStretch(0, 3)
- self.horizontalLayout.setStretch(1, 1)
- MainWindow.setCentralWidget(self.centralwidget)
- self.menubar = QtWidgets.QMenuBar(MainWindow)
- self.menubar.setGeometry(QtCore.QRect(0, 0, 818, 23))
- self.menubar.setObjectName("menubar")
- MainWindow.setMenuBar(self.menubar)
- self.statusbar = QtWidgets.QStatusBar(MainWindow)
- self.statusbar.setObjectName("statusbar")
- MainWindow.setStatusBar(self.statusbar)
-
- self.retranslateUi(MainWindow)
- self.pushButton.clicked.connect(MainWindow.saveNum) # type: ignore
- QtCore.QMetaObject.connectSlotsByName(MainWindow)
-
- def retranslateUi(self, MainWindow):
- _translate = QtCore.QCoreApplication.translate
- MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))