Electron qt开发教程

模块安装打包

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++
cpp 复制代码
#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
javascript 复制代码
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使用
vbscript 复制代码
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使用
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-start GitHub - qtoolkit/qtk: QTK 是一套基于HTML5 Canvas实现的, 专注于桌面/移动应用程序开发的框架。

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

Introduction | Electron

Electron

node与Electron版本对应

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


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

相关推荐
Captaincc41 分钟前
AI用量v0.1.11更新发布 新增 jusage doctor 诊断指令 托盘展示token 和余额 新增 AutoClaw 支持
前端·后端·vibecoding
计算机魔术师2 小时前
德国Wiki被黑后两周,OpenAI终于把模型失控的账本摊开了
前端
Quz3 小时前
QML 常见的四种导航布局
qt
kyriewen3 小时前
我让 AI 当面试官面了我一轮:第 3 个追问我就卡住了(附 10 道追问清单)
前端·面试·ai编程
IT_陈寒3 小时前
Python的GIL把我坑惨了,多线程跑得比单线程还慢
前端·人工智能·后端
前端snow3 小时前
ai agent --- 多agent框架之图编排引擎-langgraph
前端
竹林8183 小时前
OmniPic Studio v3.2.1 核心技术架构与全平台发版解析文档
前端·浏览器
JamesZhang800783 小时前
页面内存只涨不跌? 一次泄漏排查, 牵出 WeakMap 的诞生
前端
Z小明3 小时前
第 6 章 组件进阶
前端·vue.js
江华森3 小时前
HTTP请求的完整过程详解:从DNS解析到TCP挥手的微秒级实战分析
前端