PYQT/QT 开发VUE GUI应用程序(持续更新)
PYQT/QT 开发VUE GUI应用程序(持续更新)参考列表博主文章: Qt+vue开发桌面应用程序知乎文章 超级详细!: 基于 QWebChannel 的前端通信方案工具书籍: 《PYQT5快速开发与实战》使用技术栈VUE CLIelement等框架均可QWebEngineView 与 静态页面交互需要熟悉QT qrc资源库的操作PyQt5如果需要在PYQT5上进行VUE-element的开发
PYQT/QT 开发VUE GUI应用程序(持续更新)
参考列表
博主文章
: Qt+vue开发桌面应用程序
知乎文章 超级详细!:
基于 QWebChannel 的前端通信方案
工具书籍:
《PYQT5快速开发与实战》
使用技术栈
- VUE CLI
- element等框架均可
- QWebEngineView 与 静态页面交互
- 需要熟悉QT qrc资源库的操作
- PyQt5
如果需要在PYQT5上进行VUE-element的开发之类 可以参考此文章 请仔细观看此文章
提示:在资源文件的打包上也有大坑
持续更新避免踩坑 如果能做到此页面的联调成功 基本上就可以通过VUE-CLI完整的开发一个桌面应用了
以后也许会更新 VUE-ELEMENT 在PYQT上的应用
能实现vue-cli和pycharm pyqt的联调后 开发起来就不是很麻烦了 主要是nodejs操作GPIB或其他设备仪器太复杂了陷入了调用DLL的地狱,使用了ZMQ, WEBSOCKET等还是觉得体验实在是太割裂了,完全不像是nativeGUI,但是这样开发 还是有点electorn的体验了
1.联调效果 python传递数据到前台1S更新一次
2.调试教程
2.1. 准备调试
可以参考我另一篇博文 如何调用静态html
调试准备 因为我是使用的pycharm 所以先要对Run/Debug Configurations进行一个设置
再如图位置 输入 < ;QTWEBENGINE_REMOTE_DEBUGGING=9927 > 即在9927端口进行调试
2.2.将调试端口加入到浏览器书签中
2.3.启动python代码 看到如下提示
2.4.进入http://127.0.0.1:9927/端口点击项目查看Console 并进行联调
3.过一遍Python端需要的模块
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2021/4/15 9:29
# @Author : Link
# @Site :
# @File : demo_one.py
# @Software: PyCharm
import itertools
import json
import sys
import string
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl, QTimer
from MySharedObject import MySharedObject
from PyQt5.QtWebChannel import QWebChannel
# from qweb.dist import src_rc
# 创建一个 application实例
app = QApplication(sys.argv)
win = QWidget()
win.setWindowTitle('Web页面中的JavaScript与 QWebEngineView交互例子')
# 创建一个垂直布局器
layout = QVBoxLayout()
win.setLayout(layout)
# 创建一个 QWebEngineView 对象
view = QWebEngineView()
# htmlUrl = 'qrc:/index.html'
htmlUrl = 'http://localhost:8080/' # 远程到nodejs服务调试
channel = QWebChannel()
myObj = MySharedObject()
channel.registerObject("bridge", myObj) # 注册对象到VUE中 主要!
view.load(QUrl(htmlUrl))
# 创建一个 QWebChannel对象,用来传递pyqt参数到JavaScript
view.page().setWebChannel(channel)
def generator_a_z(): # 向前端发送数据
length = 1
while length:
for letters in itertools.product(string.ascii_uppercase,
repeat=length):
yield ''.join(letters)
length += 1
s = generator_a_z()
timer = QTimer()
timer.timeout.connect(lambda: myObj.connectSignal.emit(
json.dumps({
"code": 200,
"func": "messageShow",
"data": next(s)
})
))
timer.start(1000)
# 把QWebView和button加载到layout布局中
layout.addWidget(view)
# 显示窗口和运行app
win.show()
sys.exit(app.exec_())
# http://127.0.0.1:9927/ # 调试地址
# -*- coding: utf-8 -*-
# @File : MySharedObject.py
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
from PyQt5.QtCore import pyqtProperty
from PyQt5.QtWidgets import QWidget, QMessageBox
class MySharedObject(QWidget):
connectSignal = pyqtSignal(str) # 注册到VUE中
@pyqtSlot(str)
def foo(self):
print('aaa')
def __init__(self):
super(MySharedObject, self).__init__()
def _getStrValue(self):
#
return '100'
def _setStrValue(self, str):
#
print('获得页面参数 :%s' % str)
QMessageBox.information(self, "Information", '获得页面参数 :%s' % str)
# 需要定义对外发布的方法 静态页面测试通过 但VUE中暂时还没用到
strValue = pyqtProperty(str, fget=_getStrValue, fset=_setStrValue)
4.VUE CLI端
根据官方文档初始化一个项目 地址
注意 一定不要 Eslint或是关闭它
, 当然大神可以不用管
项目结构
qwebchannel.js只要PYQT中下载了PYQTWebEngine 后 用everything本地搜索就可以了,如果是下载的比较新 就不需要对这个文件做任何修改 不然可能需要 export QWebChannel
主要入口重要
import { QWebChannel } from './qwebchannel'
const model = 'eng' // 可以写在env文件中
/*
这段代码 主要是为了能在离开QT启动的环境下 调用QWebChannel
不然会报错无qt.webChannelTransport程序无法运行
*/
if (model === 'pro') { // 使用pro模式可以在离开QT环境下调试
window.qt = {
webChannelTransport: {
send() {
console.log(`
QWebChannel simulator activated !
`)
}
}
}
}
/*
这个MAP 是为了做一个funtino的缓存 在view中建立页面的时候 如果需要从python直接控制view页面
就将function 注册到如下MAP中
为什么这么做的原因:因为web页面启动起来后 QWebChannel可能还未触发 我这边估计会延迟3s左右
在这个时候 qtWebChannel 还是空值 无法进行connect
mounted() {
this.$QtCallBackDict.messageShow = this.updateMessage
},
methods:{
updateMessage(text){
this.message = text
},
}
*/
export var callBackDict = {
messageShow: null,
newMessage: null,
}
export var qtWebChannel = null; //导出qtWebChannel,供其他页面调用
new QWebChannel(qt.webChannelTransport, (channel) => {
// all published objects are available in channel.objects under
// the identifier set in their attached WebChannel.id property
console.log(channel.objects)
qtWebChannel = channel.objects.bridge;
callBack()
});
/*
bridge对象传入后 进行初始化
*/
function callBack() {
console.log("初始化")
qtWebChannel.connectSignal.connect(connectSignalCallBack)
}
/*
对python端 MySharedObject下 connectSignal传来的json数据进行一个处理
*/
function connectSignalCallBack(jsonString) {
/*
res: {
code: 200/400 400就是后台有问题
func: string 在mount中载入
data: Dict 传入到view函数中
}
*/
const res = JSON.parse(jsonString)
console.info(res)
if (res.code === 400) {
console.log(res)
return
}
// 可以自己在这里加上校验之类 以免funcname不存在
callBackDict[res.func](res.data)
}
VUE引入
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
// 将函数暴露到Vue中
import { callBackDict, qtWebChannel } from './utils/requests'
Vue.prototype.$QtCallBackDict = callBackDict
Vue.prototype.$QtWebChannel = qtWebChannel
new Vue({
render: h => h(App),
}).$mount('#app')
更改APP.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<!-- <HelloWorld msg="Welcome to Your Vue.js App" /> -->
<input v-model="message" type="text" />
</div>
</template>
<script>
// import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HelloWorld,
},
data() {
return {
message: "aa",
};
},
mounted() {
this.$QtCallBackDict.messageShow = this.updateMessage
},
methods:{
updateMessage(text){
this.message = text
},
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
5.启动 那个先启动都行 作为调试阶段只关注是否能链接成功
更多推荐
所有评论(0)