☰
Electron qt开发教程
2026/11/2 1:11:18 网站建设 项目流程
模块安装打包

npm install -g electron-forge
electron-forge init my-project --template=vue
npm start //进入目录启动
//打包成一个目录到out目录下,注意这种打包一般用于调试,并不是用于分发
npm run package
//打出真正的分发包,放在out\make目录下
npm run make

npx @electron-forge/cli@latest import
npx create-electron-app my-app

npm install mousetrap //快捷键绑定库

npm install worker_threads //工作线程模块
npm install worker-loader //
npm init //C++项目目录下初始化项目
npm install --global --production windows-build-tools

electron 将pc端(vue)页面打包为桌面端应用-CSDN博客
快速体验

npm install -g electron-prebuilt
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install && npm start

cnpm install electron-packager -g
"scripts": {"package":"electron-packager . HelloWorld --platform=win32 --arch=x64 --icon=computer.ico --out=./out --asar --app-version=0.0.1 --overwrite --ignore=node_modules"
}
npm run package

GitHub - electron/electron-api-demos: Explore the Electron APIs

@python "%~dp0gyp_main.py" %*

JS调用C++
#include <node.h> #include <v8.h> using namespace v8; // 传入了两个参数,args[0] 字符串,args[1] 回调函数 void hello(const FunctionCallbackInfo<Value>& args) { // 使用 HandleScope 来管理生命周期 Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); // 判断参数格式和格式 if (args.Length() < 2 || !args[0]->IsString()) { isolate->ThrowException(Exception::TypeError( String::NewFromUtf8(isolate, "Wrong arguments"))); return; } // callback, 使用Cast方法来转换 Local<Function> callback = Local<Function>::Cast(args[1]); Local<Value> argv[1] = { // 拼接String String::Concat(Local<String>::Cast(args[0]), String::NewFromUtf8(isolate, " world")) }; // 调用回调, 参数: 当前上下文,参数个数,参数列表 callback->Call(isolate->GetCurrentContext()->Global(), 1, argv); } // 相当于在 exports 对象中添加 { hello: hello } void init(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", hello); } // 将 export 对象暴露出去 // 原型 `NODE_MODULE(module_name, Initialize)` NODE_MODULE(test, init); //方法暴露 void Method(const FunctionCallbackInfo<Value>& args) { Isolate* isolate = args.GetIsolate(); args.GetReturnValue().Set(String::NewFromUtf8( isolate, "world").ToLocalChecked()); } void Initialize(Local<Object> exports) { NODE_SET_METHOD(exports, "hello", Method); } NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) extern "C" NODE_MODULE_EXPORT void NODE_MODULE_INITIALIZER(Local<Object> exports, Local<Value> module, Local<Context> context) { /* Perform addon initialization steps here. */ } int main(int argc, char* argv[]) { // Create a stack-allocated handle scope. HandleScope handle_scope; // Create a new context. Handle<Context> context = Context::New(); // Enter the created context for compiling and // running the hello world script. Context::Scope context_scope(context); // Create a string containing the JavaScript source code. Handle<String> source = String::New("'Hello' + ', World!'"); // Compile the source code. Handle<Script> script = Script::Compile(source); // Run the script to get the result. Handle<Value> result = script->Run(); // Convert the result to an ASCII string and print it. String::AsciiValue ascii(result); printf("%s\n", *ascii); return 0; } //create accessor for string username global->SetAccessor(v8::String::New("user"),userGetter,userSetter); //associates print on script to the Print function global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); //注册类对象 Handle<FunctionTemplate> point_templ = FunctionTemplate::New(); point_templ->SetClassName(String::New("Point")); Handle<ObjectTemplate> point_proto = point_templ->PrototypeTemplate(); point_proto->Set("method_a", FunctionTemplate::New(PointMethod_A)); point_proto->Set("method_b", FunctionTemplate::New(PointMethod_B)); //设置指针个数 Handle<ObjectTemplate> point_inst = point_templ->InstanceTemplate(); point_inst->SetInternalFieldCount(1); //创建实例 Handle<Function> point_ctor = point_templ->GetFunction(); Local<Object> obj = point_ctor->NewInstance(); obj->SetInternalField(0, External::New(p)); //获取类指针处理 Handle<Value> PointMethod_A(const Arguments& args) 2. { 3. Local<Object> self = args.Holder(); 4. Local<External> wrap = Local<External>::Cast(self->GetInternalField(0)); 5. void* ptr = wrap->Value(); 6. static_cast<Point*>(ptr)->Function_A(); 7. return Integer::New(static_cast<Point*>(ptr)->x_); 8. } //向MakeWeak注册的callback. void CloudAppWeakReferenceCallback(Persistent<Value> object , void * param) { if (CloudApp* cloudapp = static_cast<CloudApp*>(param)) { delete cloudapp; } } //将C++指针通过External保存为Persistent对象,避免的指针被析构 Handle<External> MakeWeakCloudApp(void* parameter) { Persistent<External> persistentCloudApp = Persistent<External>::New(External::New(parameter)); //MakeWeak非常重要,当JS世界new一个CloudApp对象之后 //C++也必须new一个对应的指针。 //JS对象析构之后必须想办法去析构C++的指针,可以通过MakeWeak来实现, //MakeWeak的主要目的是为了检测Persistent Handle除了当前Persistent //的唯一引用外,没有其他的引用,就可以析构这个Persistent Handle了, //同时调用MakeWeak的callback。这是我们可以再这个callback中delete //C++指针 persistentCloudApp.MakeWeak(parameter, CloudAppWeakReferenceCallback); return persistentCloudApp; } void Print(const v8::FunctionCallbackInfo<v8::Value>& args) { bool first = true; for (int i = 0; i < args.Length(); i++) { v8::HandleScope handle_scope(args.GetIsolate()); if (first) { first = false; } else { printf(" "); } v8::String::Utf8Value str(args[i]); const char* cstr = ToCString(str); printf("%s", cstr); const char* s_result = "print call succeed\n"; v8::Local<v8::String> v_result = v8::String::NewFromUtf8(args.GetIsolate(), s_result, v8::NewStringType::kNormal).ToLocalChecked(); args.GetReturnValue().Set(v_result); } printf("\n"); fflush(stdout); } v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate); // Bind the global 'print' function to the C++ Print callback. global->Set( v8::String::NewFromUtf8(isolate, "print", v8::NewStringType::kNormal) .ToLocalChecked(), v8::FunctionTemplate::New(isolate, Print)); Local<Context> context = v8::Context::New(isolate, NULL, global); Isolate *isolate = args.GetIsolate(); Local<Object> opts = args[0]->ToObject(); Local<Number> mode = opts->Get(String::NewFromUtf8(isolate, "mode"))->ToNumber(isolate); static void DeleteInstance(void* data) { // 将 `data` 转换为该类的实例并删除它。 } node::AddEnvironmentCleanupHook(DeleteInstance) //在销毁环境之后被删除 JS调用C++函数,就是通过FunctionTemplate和ObjectTemplate进行扩展的。 V8的External就是专门用来封装(Wrap)和解封(UnWrap)C++指针的
V8_EXPORT
V8_INLINE
v8::Handle<
v8::Local<
const v8::Arguments
const v8::FunctionCallbackInfo<v8::Value>& 不定参数
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate);
G
String::NewFromUtf8Literal(isolate, "isNull")
String::Cast
isolate->GetCurrentContext()
NODE_SET_PROTOTYPE_METHOD(tpl, "x", X);
https://github.com/alibaba/jsni.git
nodeqt
const qt = require("./lib/qt"); const app = new qt.QApplication(); const window = new qt.QMainWindow(); const box = new qt.QWidget(); box.setStyleSheet("background-color:red;"); box.resize(300, 300); box.move(300, 300); box.setParent(window); window.resizeEvent((width, height) => { console.log("Resized1", width, height); console.log(width, height); }); window.closeEvent(() => { console.log("Closing"); }); box.resizeEvent((width, height) => { console.log("Resized2", width, height); }); box.mousePressEvent(() => console.log("CLICKED!")); box.mouseReleaseEvent(() => console.log("UNCLICKED!")); box.setMouseTracking(true); box.mouseMoveEvent((x, y) => console.log(`MOUSE MOVED! x: ${x} y: ${y}`)); box.enterEvent(() => console.log("MOUSE ENTERED!")); box.leaveEvent(() => console.log("MOUSE LEFT!")); const label = new qt.QLabel(box); console.log("Size hint", label.sizeHint()); console.log("Height", label.height()); label.setText('<span style="">dsawewwww<span style="">Hello2</span></span>'); label.adjustSize(); const label2 = new qt.QLabel(window); const pix = new qt.QPixmap(); pix.load("/home/kusti8/Pictures/test_small.jpg"); pix.scaled(300, 300, qt.AspectRatioMode.IgnoreAspectRatio); label2.setPixmap(pix); label2.adjustSize(); label2.setStyleSheet("background-color: red;"); label2.move(300, 600); label2.setScaledContents(false); label2.setAlignment(qt.Alignment.AlignCenter); label2.show(); const lineedit = new qt.QLineEdit(window); lineedit.move(100, 100); lineedit.textChangedEvent(text => console.log("text changed", text)); lineedit.show(); const combobox = new qt.QComboBox(window); combobox.currentTextChangedEvent(text => console.log("New combo", text)); combobox.setEditable(true); combobox.addItem("Test1"); combobox.addItem("Test2"); combobox.addItem("Test3"); box.show(); box.clear(); console.log("set parent"); window.show(); console.log("set parent"); app.aboutToQuitEvent(() => console.log("Quitting")); console.log("Height", label.height()); console.log(qt.desktopSize()); app.exec();
GitHub - arturadib/node-qt: C++ Qt bindings for Node.js

mirrors_CoderPuppy/node-qt

GitHub - anak10thn/node-qt5

GitHub - NickCis/nodeQt: Qt binding for Node

GitHub - a7ul/mdview-nodegui: A Markdown editor in NodeGui

GitHub - kusti8/node-qt-napi: Node.js bindinds for Qt5, using NAPI

GitHub - nodegui/qode: DEPRECATED: Please see https://github.com/nodegui/qodejs instead

GitHub - svalaskevicius/qtjs-generator: Qt API bindings generator for Node.js

C++ 插件 | Node.js v22 文档

GitHub - nodegui/nodegui-starter: A starter repo for NodeGui projects

GitHub - anak10thn/qhttpserver: HTTP server implementation for Qt based on node.js' http parser

GitHub - anak10thn/chrome-app-samples: Chrome Apps

GitHub - magne4000/node-qtdatastream: Nodejs lib which can read/write Qt formatted Datastreams

GitHub - fwestrom/qtort-microservices: A simple micro-services framework for Node.js.

GitHub - ivan770/PiQture: Screenshot tool based on Electron

GitHub - miskun/qtc-sdk-node: Qt Cloud Services SDK for Node.js

v8: include/v8.h File Reference

nodegyp

node-gyp -j 8 configure
node-gyp -j 8 build
"install": "node-gyp -j 8 rebuild --arch=ia32"
"install": "node-gyp -j 8 rebuild --arch=x86"

https://github.com/kusti8/node-qt-napi/releases/download/0.0.4/qt-v0.0.4-4-win32-x64.tar.gz

工程搭建方式

gyp文件样例

TortoiseGit bash使用
set PRJ_PATH=E:\workspace\test\Web-Dev-For-Beginners\nodeqt TortoiseGitProc.exe /command:commit /path:"%PRJ_PATH%\nodegyp" /logmsgfile:"%PRJ_PATH%\refModify.txt" /bugid:1 /closeonend:2% TortoiseGitProc.exe /command:pull /path:"%PRJ_PATH%\nodegyp" /closeonend:2 TortoiseGitProc.exe /command:push /path:"%PRJ_PATH%\nodegyp" /closeonend:2 pause
git bash使用
git config --global user.name "your-name" git config --global user.email "your-email" git init @ Initialize a git repositor git status @Check status git add . git add [file or folder name] git reset //将文件还原到上一个commit git reset [file or folder name] //特定文件还原到上一个commit git commit -m "first commit" git remote add origin https://github.com/username/repository_name.git //添加远程仓库地址 git push -u origin main //This sends your commits in your "main" branch to GitHub git branch [branch-name] //Create a branch git checkout [branch-name] //Switch to working branch git checkout main git pull //Combine your work with the main branch git checkout [branch_name] git merge main //conflicts combine the changes happens in your working branch. git push --set-upstream origin [branch-name] //Send your work to GitHub git branch -d [branch-name] //clean up both your local branch git pull
参考

GitHub - electron/electron-api-demos: Explore the Electron APIsExplore the Electron APIs. Contribute to electron/electron-api-demos development by creating an account on GitHub.https://github.com/electron/electron-api-demosQuick Start | ElectronThis guide will step you through the process of creating a barebones Hello World app in Electron, similar to electron/electron-quick-start.https://electronjs.org/docs/tutorial/quick-starthttps://github.com/electron/electron-quick-starthttps://github.com/electron/electron-quick-startGitHub - qtoolkit/qtk: QTK 是一套基于HTML5 Canvas实现的, 专注于桌面/移动应用程序开发的框架。

https://github.com/sindresorhus/awesome-electron

Introduction | Electron

Electron


node与Electron版本对应

GitHub - atom/atom: :atom: The hackable text editor

GitHub - nodejs/node-addon-api: Module for using Node-API from C++

GitHub - glencornell/TinyEventLib: A tiny clean room implementation of the event processing loop in Qt


创作不易,小小的支持一下吧!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询