QT 6
Qt 类库里大量的类根据功能分为各种模块, 这些模块又分为以下几大类:
- Qt 基本模块(Qt Essentials): 提供了 Qt 在所有平台上的基本功能;
- Qt 附加模块(Qt Add-Ons): 实现一些特定功能的提供附加价值的模块;
- 增值模块(Value-AddModules): 单独发布的提供额外价值的模块或工具;
- 技术预览模块(Technology Preview Modules): 一些处于开发阶段, 但是可以作为技术预览使用的模块;
- Qt 工具(Qt Tools): 帮助应用程序开发的一些工具;
QT5 All Modules Qt6 All Modules Qt6 All Classes 官方示例教程 QT 开发记录归档 QT 发布 BLOG New Features in Qt 6.0
Qt Core
QCore non-graphical classes used by other modules. 其他模块使用的QCore非图形类;
包括: QString, QObject 信号与槽, 容器类, 多线程 等核心QT内容
引入 If you use qmake to build your projects, Qt6Core is linked by default.
QT 容器类 (Container Classes)
Container Classes
The Qt library provides a set of general purpose template-based container classes. These classes can be used to store items of a specified type. For example, if you need a resizable array of QStrings, use QVector<QString>.
These container classes are designed to be lighter, safer, and easier to use than the STL containers. If you are unfamiliar with the STL, or prefer to do things the “Qt way”, you can use these classes instead of the STL classes.
The container classes are implicitly shared, they are reentrant, and they are optimized for speed, low memory consumption, and minimal inline code expansion, resulting in smaller executables. In addition, they are thread-safe in situations where they are used as read-only containers by all threads used to access them. *容器类是隐式共享的, 它们是可重入的, 并且针对速度, 低内存消耗和最小的内联代码扩展进行了优化, 从而产生更小的可执行文件; 此外, 在所有用于访问它们的线程都将它们用作只读容器的情况下, 它们是线程安全的; * 简而言之,它们默认是线程只读安全
For traversing the items stored in a container, you can use one of two types of iterators: Java-style iterators and STL-style iterators. The Java-style iterators are easier to use and provide high-level functionality, whereas the STL-style iterators are slightly more efficient and can be used together with Qt’s and STL’s generic algorithms.
迭代器 遍历访问 (Java-Style Iterators)
| Containers | Read-only iterator | Read-write iterator |
|---|---|---|
QList<T>, QQueue<T> | QListIterator<T> | QMutableListIterator<T> |
QLinkedList<T> | QLinkedListIterator<T> | QMutableLinkedListIterator<T> |
QVector<T>, QStack<T> | QVectorIterator<T> | QMutableVectorIterator<T> |
QSet<T> | QSetIterator<T> | QMutableSetIterator<T> |
| QMap<Key, T>, QMultiMap<Key, T> | QMapIterator<Key, T> | QMutableMapIterator<Key, T> |
| QHash<Key, T>, QMultiHash<Key, T> | QHashIterator<Key, T> | QMutableHashIterator<Key, T> |
关于指针变量 T的类型为非指针, 这时候直接调用clear()方法就可以释放了, 如果是指针就要在clear()函数前使用 qDeleteAll();
IO处理
QIODevice provides both a common implementation and an abstract interface for devices that support reading and writing of blocks of data, such as QFile, QBuffer and QTcpSocket. QIODevice is abstract and cannot be instantiated, but it is common to use the interface it defines to provide device-independent I/O features. For example, Qt’s XML classes operate on a QIODevice pointer, allowing them to be used with various devices (such as files and buffers).
二进制流
读
QFile file("F:\\test\\stream\\test5m.ts");
file.open(QFile::OpenModeFlag::ReadOnly);
QDataStream aStream(&file);
char * pData = new char[4096];
int len = -1;
int count = 0;
while( (len=aStream.readRawData(pData, 4096)) > 0){
const QByteArray data(pData, len);
this->webSocket->sendBinaryMessage(data);
this->webSocket->flush();
qDebug()<<" send "<<count<<" count";
count++;
}写
QFile file("f:/test/sdk_to_ffmpegNoProcess.dat");
file.open(QFile::OpenModeFlag::ReadWrite );
QDataStream aStream(&file);
aStream.writeRawData()文本流
TODO
JSON支持
The JSON support in Qt provides an easy to use C++ API to parse, modify and save JSON data. It also contains support for saving this data in a binary format that is directly “mmap”-able and very fast to access.(可以保存为二进制格式, 直接快速访问)
More details about the JSON data format can be found at json.org and in RFC-4627.
//QJsonObject to String btyte
QByteArray jsonBytes = QJsonDocument(json).toJson(QJsonDocument::Compact);
//String btyte to QJsonObject
QJsonDocument doc = QJsonDocument::fromJson( request.getBody() );
QJsonObject jsonNode = doc.object();数据类
class Character
{
Q_GADGET;
public:
enum ClassType {
Warrior, Mage, Archer
};
Q_ENUM(ClassType)
Character();
Character(const QString &name, int level, ClassType classType);
QString name() const;
void setName(const QString &name);
int level() const;
void setLevel(int level);
ClassType classType() const;
void setClassType(ClassType classType);
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
void print(int indentation = 0) const;
private:
QString mName;
int mLevel;
ClassType mClassType;
};
class Level
{
public:
Level() = default;
Level(const QString &name);
QString name() const;
QList<Character> npcs() const;
void setNpcs(const QList<Character> &npcs);
void read(const QJsonObject &json);
void write(QJsonObject &json) const;
void print(int indentation = 0) const;
private:
QString mName;
QList<Character> mNpcs;
};
序列化
//读文件 /QByteArray
bool Game::loadGame(Game::SaveFormat saveFormat)
{
QFile loadFile(saveFormat == Json
? QStringLiteral("save.json")
: QStringLiteral("save.dat"));//二进制格式
if (!loadFile.open(QIODevice::ReadOnly)) {
qWarning("Couldn't open save file.");
return false;
}
QByteArray saveData = loadFile.readAll();
//1. 需要先实例 QJsonDocument 对象
QJsonDocument loadDoc(saveFormat == Json
? QJsonDocument::fromJson(saveData)
: QJsonDocument(QCborValue::fromCbor(saveData).toMap().toJsonObject()));
//2. 根据QJsonDocument获取 QJsonObject
read(loadDoc.object());
QTextStream(stdout) << "Loaded save for "
<< loadDoc["player"]["name"].toString()
<< " using "
<< (saveFormat != Json ? "CBOR": "JSON") << "...\n";
return true;
}
void Game::read(const QJsonObject &json)
{
if (json.contains("player") && json["player"].isObject())
mPlayer.read(json["player"].toObject());
if (json.contains("levels") && json["levels"].isArray()) {
QJsonArray levelArray = json["levels"].toArray();
mLevels.clear();
mLevels.reserve(levelArray.size());
for (int levelIndex = 0; levelIndex < levelArray.size(); ++levelIndex) {
QJsonObject levelObject = levelArray[levelIndex].toObject();
Level level;
level.read(levelObject);
mLevels.append(level);
}
}
}
void Level::read(const QJsonObject &json)
{
//key , value, 字符串
if (json.contains("name") && json["name"].isString())
mName = json["name"].toString();
//数组
if (json.contains("npcs") && json["npcs"].isArray()) {
QJsonArray npcArray = json["npcs"].toArray();
mNpcs.clear();
mNpcs.reserve(npcArray.size());
for (int npcIndex = 0; npcIndex < npcArray.size(); ++npcIndex) {
QJsonObject npcObject = npcArray[npcIndex].toObject();
Character npc;
npc.read(npcObject);
mNpcs.append(npc);
}
}
}
void Character::read(const QJsonObject &json)
{
if (json.contains("name") && json["name"].isString())
mName = json["name"].toString();
//浮点型
if (json.contains("level") && json["level"].isDouble())
mLevel = json["level"].toInt();
if (json.contains("classType") && json["classType"].isDouble())
mClassType = ClassType(json["classType"].toInt());
}反序列化
bool Game::saveGame(Game::SaveFormat saveFormat) const
{
QFile saveFile(saveFormat == Json
? QStringLiteral("save.json")
: QStringLiteral("save.dat"));//二进制格式
if (!saveFile.open(QIODevice::WriteOnly)) {
qWarning("Couldn't open save file.");
return false;
}
QJsonObject gameObject;
write(gameObject);
saveFile.write(saveFormat == Json
? QJsonDocument(gameObject).toJson()
: QCborValue::fromJsonValue(gameObject).toCbor());
return true;
}
void Game::write(QJsonObject &json) const
{
QJsonObject playerObject;
// Character mPlayer;
mPlayer.write(playerObject);
//key value, 根节点
json["player"] = playerObject;
QJsonArray levelArray;
for (const Level &level: mLevels) {
QJsonObject levelObject;
level.write(levelObject);
levelArray.append(levelObject);
}
//数组
json["levels"] = levelArray;
}
void Character::write(QJsonObject &json) const
{
json["name"] = mName;
json["level"] = mLevel;
json["classType"] = mClassType;
}
void Level::write(QJsonObject &json) const
{
json["name"] = mName;
QJsonArray npcArray;
for (const Character &npc: mNpcs) {
QJsonObject npcObject;
//Character npc;
npc.write(npcObject);
npcArray.append(npcObject);
}
json["npcs"] = npcArray;
}
//写入文件
bool Game::saveGame(Game::SaveFormat saveFormat) const
{
QFile saveFile(saveFormat == Json
? QStringLiteral("save.json")
: QStringLiteral("save.dat"));
if (!saveFile.open(QIODevice::WriteOnly)) {
qWarning("Couldn't open save file.");
return false;
}
QJsonObject gameObject;
write(gameObject);
saveFile.write(saveFormat == Json
? QJsonDocument(gameObject).toJson()
: QCborValue::fromJsonValue(gameObject).toCbor());
return true;
}Qt D-Bus
Classes for inter-process communication over the D-Bus protocol. 通过D-Bus协议进行进程间通信的类;
Qt GUI
Base classes for graphical user interfaces. 用户图形接口的基本class
图片绘制
QImage image(300,300,QImage::Format_RGB32);
image.fill(0xffffff);
QPainter painter(&image);
painter.setPen(QColorConstants::Green);
QList<QRectF> rectangles;
rectangles.append(QRectF(25,25,200,150));
rectangles.append(QRectF(30,30,220,150));
painter.drawRects(rectangles);
image.save("E:\\content-for-work\\2022-03PaddlePaddle\\qimg.png");Qt Network
Classes to make network programming easier and more portable 包含: 网络相关编程, socket websocket, http
引入
CMake
find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
实在引入
1、要把“mytarget”换成项目名称
2、要去掉“PRIVATE”
3、find_package 和target_link_libraries要分开写
find_package(Qt6 COMPONENTS Network REQUIRED)
target_link_libraries(ip-report Qt6::Network)
qmake
QT += network
TCP/IP Socket
Using TCP with QTcpSocket and QTcpServer TCP (Transmission Control Protocol) is a low-level network protocol used by most Internet protocols, including HTTP and FTP, for data transfer. It is a reliable, stream-oriented, connection-oriented transport protocol. It is particularly well suited to the continuous transmission of data.
Using TCP with QTcpSocket and QTcpServer
TcpServer 服务端
QTcpServer tcpServer = new QTcpServer();
const quint16 port= 8864;
const QString localhonst = "127.0.0.1";
QHostAddress host(localhonst);
tcpServer->listen(host, port);//如果是继承 QTcpServer 的话有个virtual void incomingConnection(qintptr handle);虚方法, 可以获得客户端连接
void SessionServer::incomingConnection(qintptr socketDescriptor){
this->client = new QTcpSocket();
this->client->setSocketDescriptor(socketDescriptor);
}//如果是使用信号 void newConnection(); 可以通过virtual QTcpSocket *nextPendingConnection();获得客户端连接
QTcpSocket 正确的读写
关键是:
waitForReadyRead 该函数将阻塞, 直到可以读取新数据并且发出readyRead()信号为止; 该函数将在毫秒毫秒后超时; 默认超时为30000毫秒;
waitForBytesWritten 该函数将阻塞, 直到在套接字上至少写入了一个字节并且已发出bytesWritten()信号为止; 该函数将在毫秒毫秒后超时; 默认超时为30000毫秒;
//文本流
QTextStream socketStream(this->client);
while (!this->isInterruptionRequested() ){
this->client->waitForReadyRead(200);
QString line = socketStream.readLine();
/////// 处理读
/// std::cout<<"raw="<<line.toStdString()<<std::endl;
if( !line.isEmpty() ){
std::cout<<"rawString"<<line.toStdString()<<std::endl;
}
/////// 处理写
if(! responses.isEmpty() ){
Response res = responses.dequeue();
QByteArray rbytes = res.getJsonByte();
rbytes.append("\r\n");
client->write(rbytes);
client->waitForBytesWritten(200);
}
}Call listen() to have the server listen for incoming connections. The newConnection() signal is then emitted each time a client connects to the server.
Call nextPendingConnection() to accept the pending connection as a connected QTcpSocket. The function returns a pointer to a QTcpSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client.
//其一
//tcp 服务端对象
QTcpServer tcpServer = new QTcpServer;
///绑定本机端口 监听
QHostAddress host(localhonst);
bool b = tcpServer->listen(host, port);
//有新连接时发射信号 newConnection
//再调用 nextPendingConnection, 可以获取客户端的 QTcpSocket 对象指针
//其二
// 或者继承 QTcpServer, 重写 virtual void incomingConnection(qintptr handle);
// 有新连接时会调用, 参数handle 句柄(就是 SocketDescriptor )
this->client = new QTcpSocket();
this->client->setSocketDescriptor(this->handle);
//断开信号
QObject::connect(this->client,SIGNAL(disconnected() ) , this, SLOT(handleDisconnected() ) );
//文本流
QTextStream socketStream(this->client);
//读取
this->client->waitForReadyRead(200);QTcpSocket 客户端
参考服务端的 连接使用 virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol); void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite);
然后使用 waitForConnected 等待连接成功 [virtual]bool QAbstractSocket::waitForConnected(int msecs = 30000)
最后就可以使用 Stream 读写 QTcpSocket
Web Socket
#include "echoserver.h"
#include "QtWebSockets/qwebsocketserver.h"
#include "QtWebSockets/qwebsocket.h"
#include <QtCore/QDebug>
QT_USE_NAMESPACE
EchoServer::EchoServer(quint16 port, bool debug, QObject *parent) :
QObject(parent),
//NonSecureMode 是否wss的参数
m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
QWebSocketServer::NonSecureMode, this)),
m_debug(debug)
{
if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
if (m_debug)
qDebug() << "Echoserver listening on port" << port;
connect(m_pWebSocketServer, &QWebSocketServer::newConnection,
this, &EchoServer::onNewConnection);
connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed);
}
}
EchoServer::~EchoServer()
{
m_pWebSocketServer->close();
qDeleteAll(m_clients.begin(), m_clients.end());
}
void EchoServer::onNewConnection()
{
QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage);
connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage);
connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected);
m_clients << pSocket;
}
void EchoServer::processTextMessage(QString message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (m_debug)
qDebug() << "Message received:" << message;
if (pClient) {
pClient->sendTextMessage(message);
}
}
void EchoServer::processBinaryMessage(QByteArray message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (m_debug)
qDebug() << "Binary Message received:" << message;
if (pClient) {
pClient->sendBinaryMessage(message);
}
}
void EchoServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
if (m_debug)
qDebug() << "socketDisconnected:" << pClient;
if (pClient) {
m_clients.removeAll(pClient);
pClient->deleteLater();
}
}QT socket对象都不允许跨线程使用 QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread
HTTP Server 服务
QT SDK 居然没有 HTTP Server 的实现; Git 找了个实现项目QtWebApp qtwebapp
- 复制 QtWebApp 目录到项目
- 参考其 Demo1 项目
在 pro 包含各项目的pri 文件
include(./QtWebApp/logging/logging.pri)
include(./QtWebApp/httpserver/httpserver.pri)
include(./QtWebApp/templateengine/templateengine.pri)
- 示例
// main.cpp
#include "http/httpprocess.h"
#include "httplistener.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
//必须带文件名, 才可以写(setValue)
QSettings *settings = new QSettings("configfile.ini",QSettings::IniFormat, &a);
settings->setValue("host", "127.0.0.1");
settings->setValue("port", 9900);
qInfo()<<"HttpListener QSettings port = "<<settings->value("port").toUInt();
new HttpListener(
settings,
new HttpProcess(&a),
&a);
return a.exec();
}// HttpProcess.cpp
#include "httpprocess.h"
HttpProcess::HttpProcess(QObject *parent)
:HttpRequestHandler{parent}{ }
void HttpProcess::service(HttpRequest& request, HttpResponse& response){
// Get a request parameters
QByteArray username=request.getParameter("username");
// Set a response header
response.setHeader("Content-Type", "text/html; charset=UTF-8");
// Generate the HTML document
response.write("<html><body>");
response.write("Hello ");
response.write(username);
response.write(" From QtWebApp </body></html>");
}代码归档
Qt QML
Classes for QML and JavaScript languages.
Qt Quick
A declarative framework for building dynamic applications with custom user interfaces.
Qt Quick Controls
Lightweight QML types for creating performant user interfaces for desktop, embedded, and mobile devices.
Qt Quick Layouts
Layouts for arranging Qt Quick items in the user interface.
Qt Quick Test
A unit test framework for QML applications, where test cases are written as JavaScript functions.
Qt Test
Classes for unit testing Qt applications and libraries.
Qt Widgets
Classes to extend Qt GUI with C++ widgets.
一些属性
sizePolicy 控制组件填充方式
-
sizeHint:大小提示 sizeHint属性保存了部件的建议大小,对于不同的部件,默认拥有不同的sizeHint;同一部件的sizeHint也有可能不同,大小随着部件内容的变化而变化。
-
minimumSizeHint:最小大小提示 minimumSizeHint保存了一个建议的最小大小提示,一般在布局中起作用。
-
sizePolicy:大小策略 sizePolicy保存了部件的默认布局行为,在水平和垂直两个方向分别起作用,控制着部件在布局管理器中的大小变化行为。说明部件在布局管理中的缩放方式。取值有:
Fixed:固定的;部件无法伸缩,它的大小只能是sizeHint()的值。 Minimum:sizeHint()给部件设置一个最小值,部件最小不能小于这个值,但是部件可以被拉伸。 Maximum:sizeHint() 给部件设置一个最大值,部件最大不能大于这个值,但是部件可以被压缩。 Preferred:优先的;sizeHint()提供给部件一个最佳大小,但是可以改变,可以拉伸或压缩。 Expanding:扩大的;sizeHint()提供给部件一个合适大小,部件可以被压缩,但是部件更倾向于被拉伸来获得更大的大小。 MinimumExpanding:sizeHint()提供给部件的大小是最小值,部件倾向于被拉伸来获得更大的大小。 Ignord:sizeHint()的值被忽略,部件将尽可能的被拉伸来获取更大的大小。
Qt GUI 模块提供了用于开发 GUI 应用程序的必要的类, 使用 qmake 构建应用程序时, Qt GUI 模块是自动被加入项目的; 如果项目中不使用 GUI 功能, 则需要在项目配置文件中加入如下的一行:
QT -= gui
其他的模块一般不会被自动加入到项目, 如果需要在项目中使用某个模块, 则可以在项目配置中添加此模块; 例如, 如果需要在项目中使用 Qt Multimedia 和 Qt Multimedia Widgets 模块, 需要在项目配置文件中加入如下的语句:
QT += multimedia multimediawidgets
需要在项目中使用 Qt SQL 模块, 就在项目配置文件中加入如下的语句:
QT += sql
如网络
QT += network
混合Web开发
QtWebkit: 在Qt5.6以前, 都是使用QtWebkit组件, 但Qt5.6以后, 移除了QtWebkit这个组件 QtWebEngine: Qt5.6以后的MSVC版本, 引进了基于Chromium的浏览器引擎 QtWebEngine QAxWidget: Qt5.6以后的mingw版本, 由于移除了QtWebkit, mingw版本不能使用QtWebEngine, 因此只能使用QAxWidget控件 QWebView 基于WebKit, QWebEngineView 基于 Chromium;
Qt6.0还不支持许多可以在Qt 5.15中找到的附加模块; 计划Qt6.2 的时候能够重新支持大部分附加组件
QWebEngineView 组件
2021年6月23日 6.2 alpha 发布 啦
The QWebEngineView class provides a widget that is used to view and edit web documents. More…
| Header: | include |
| CMake: | find_package(Qt6 COMPONENTS WebEngineWidgets REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::WebEngineWidgets) |
| qmake: | QT += webenginewidgets |
| Since: | Qt 5.4 |
| Inherits: | QWidget |
-
给
.ui添加一个 QWidget 组件 , 目前 MSVS 编译器才能编译支持 -
代码
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include "QWebEngineView.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 隐藏 状态栏
ui->statusbar->hide();
// ui->menubar->hide();//菜单栏
QWidget *widget = ui->widget;//使用这作为webview 的父容器
widget->setStyleSheet("background-color:black;");// 设置背景黑色
QWebEngineView *webview = new QWebEngineView(widget);
webview->setContextMenuPolicy( Qt::ContextMenuPolicy::NoContextMenu); // 禁用右键菜单
webview->setContentsMargins(5,5,5,5);
// 加载本地资源
// webview->load(QUrl("https://baidu.com"));
// QUrl url = QUrl("file:///E:/projects-cpp/script-helpr/html/index.html");
QUrl url = QUrl("qrc:/html/index.html");
webview->load(url);
// 需要一个布局来填满 widget // 或者 setCentralWidget(webview);
auto layoutFill = new QVBoxLayout(widget);
layoutFill->setContentsMargins(0,0,0,0); //测试
layoutFill->addWidget(webview);
}代码归档 代码归档
与 JavaScript 交互
- 桥接对象的定义
#include "webbridge.h"
#include <QObject>
#include <QString>
#include <iostream>
WebBridge::WebBridge(QObject *parent)
: QObject(parent)
{
}
void WebBridge::response(const QString &message)
{
emit sendToJs(message);
}
void WebBridge::request(const QString &message)
{
std::string res = PathAction_planning(message.toStdString());
this->response( QString::fromStdString(res) );
}
#endif - 桥接绑定
#include <QApplication>
#include <QWebEngineView>
#include <QWebChannel>
#include <QUrl>
MainFrame::MainFrame(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainFrame)
{
ui->setupUi(this);
ui->statusbar->hide();
QWidget *widget = ui->widget;
widget->setStyleSheet("background-color:black;");
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QWebEngineView *webview = new QWebEngineView(widget);
webview->setContextMenuPolicy( Qt::ContextMenuPolicy::NoContextMenu);
webview->setContentsMargins(5,5,5,5);
setCentralWidget(webview);
// 连接loadFinished信号
QObject::connect(webview, &QWebEngineView::loadFinished, [webview](bool ok) {
if (ok) {
qDebug() << "页面加载成功";
}
});
// 桥接
QWebChannel *channel = new QWebChannel(this);
WebBridge *bridge = new WebBridge(this);
channel->registerObject(QStringLiteral("WIM"), bridge);//注入 WIM 对象
webview->page()->setWebChannel(channel);
// 连接处理, js 调用桥接对象的方法
connect(bridge, &WebBridge::sendToJs, this, [webview](const QString &msg) {
webview->page()->runJavaScript(QString("response('%1')").arg(msg));
});
webview->load( QUrl("http://121.32.129.19:9977/test/index_pathpain.html") );
}
- 前端
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="./js/vue/vue@3.2.26.js"></script>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<!-- 引入样式文件 -->
<!-- <link rel="stylesheet" href="https://fastly.jsdelivr.net/npm/vant@4/lib/index.css" /> -->
<link rel="stylesheet" href="./vant/index.css" />
<script src="./vant/vant.min.js"></script>
<!-- <script src="https://lib.baomitu.com/openlayers/7.4.0/dist/ol.js"></script> -->
<script src="./js/openlayers7.4.0/ol.js"></script>
<title>农机智驾 - 路径规划测试</title>
</head>
<style>
html,body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#app {
padding: 15px;
width: 100%;
height: 100%;
display: flex;
overflow: auto;
}
</style>
<script type="module" >
window.onload = function () {
new QWebChannel(qt.webChannelTransport, function(channel) {
window.WIM = channel.objects.WIM;
console.log('WIM对象已注入:', !!WIM)
})
};
</script>
</html>注意 <script src="qrc:///qtwebchannel/qwebchannel.js"></script> 非常重要, 它是 QT内部的资源, 可以使用 QWebChannel 对象的关键
调试控制台
https://doc.qt.io/qt-6/qtwebengine-debugging.html
The Qt WebEngine module provides web developer tools that make it easy to inspect and debug layout and performance issues of any web content.
The developer tools are accessed as a local web page using a Chromium or Qt WebEngine based browser, such as the Chrome browser.
To activate the developer tools, start an application that uses Qt WebEngine with the command-line argument --remote-debugging-port=<portnumber>.
Where <port_number> refers to a local network port. The web developer tools can then be accessed by launching a browser at the address http://localhost:<port_number>.
Alternatively, the environment variable QTWEBENGINE_REMOTE_DEBUGGING can be set. It can be set as either just a port working similarly to --remote-debugging-port or given both a host address and a port. The latter can be used to control which network interface to export the interface on, so that you can access the developer tools from a remote device.
添加环境变量QTWEBENGINE_REMOTE_DEBUGGING=10066,然后直接在Qt Create中debug运行, 打开浏览器访问 http://localhost:10066 即可
代码归档
Transclude of 20250820_agriculture-registry-kter.zip