1. 创建工程
- 使用CMake创建工程
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)
project(httprequest LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
set(QT_VERSION_STR_Win32 "5.15.2/msvc2019")
set(QT_VERSION_STR_Win64 "5.15.2/msvc2019_64")
if(CMAKE_HOST_WIN32)
if(CMAKE_CL_64)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "D:/Qt/${QT_VERSION_STR_Win64}")
set(QT_QMAKE_EXECUTABLE "D:/Qt/${QT_VERSION_STR_Win64}/bin/qmake.exe")
else()
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "D:/Qt/${QT_VERSION_STR_Win32}")
set(QT_QMAKE_EXECUTABLE "D:/Qt/${QT_VERSION_STR_Win32}/bin/qmake.exe")
endif()
endif()
set(EXPAN_MACRO OFF)
if(EXPAN_MACRO)
if(MSVC)
add_compile_options(/P /EP)
endif(MSVC)
endif()
add_executable(${CMAKE_PROJECT_NAME} "")
# add_executable(${CMAKE_PROJECT_NAME} WIN32 "")
file(GLOB srcs CMAKE_CONFIGURE_DEPENDS *.cpp)
file(GLOB headers CMAKE_CONFIGURE_DEPENDS *.h)
file(GLOB forms CMAKE_CONFIGURE_DEPENDS *.ui)
file(GLOB resources CMAKE_CONFIGURE_DEPENDS *.qrc)
target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${srcs} ${forms} ${resources})
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${headers})
find_package(Qt5 COMPONENTS Core Widgets Network REQUIRED)
target_link_libraries(${CMAKE_PROJECT_NAME}
PRIVATE
Qt5::Core Qt5::Widgets Qt5::Network
)
引入QJson
add_subdirectory(qjson)
find_package(Qt5 COMPONENTS Core Widgets Network REQUIRED)
target_link_libraries(${CMAKE_PROJECT_NAME}
PRIVATE
Qt5::Core Qt5::Widgets Qt5::Network
qjson-qt5
)
创建相应的头、源文件
.
├── [1.7K] CMakeLists.txt
├── [ 26K] CMakeLists.txt.user
├── [4.0K] build
│ ├── [ 27K] ALL_BUILD.vcxproj
│ ├── [ 290] ALL_BUILD.vcxproj.filters
│ ├── [ 18K] CMakeCache.txt
│ ├── [4.0K] CMakeFiles
│ ├── [4.0K] Debug
│ ├── [ 10K] INSTALL.vcxproj
│ ├── [ 532] INSTALL.vcxproj.filters
│ ├── [ 19K] UpgradeLog.htm
│ ├── [ 29K] ZERO_CHECK.vcxproj
│ ├── [ 533] ZERO_CHECK.vcxproj.filters
│ ├── [4.0K] bin
│ ├── [1.6K] cmake_install.cmake
│ ├── [4.0K] httprequest.dir
│ ├── [5.9K] httprequest.sln
│ ├── [ 57K] httprequest.vcxproj
│ ├── [3.2K] httprequest.vcxproj.filters
│ ├── [4.0K] httprequest_autogen
│ ├── [4.0K] lib
│ ├── [4.0K] qjson
│ └── [4.0K] win32
├── [ 102] cncposition.cpp
├── [3.9K] cncposition.h
├── [ 209] main.cpp
├── [2.5K] mainwindow.cpp
├── [ 319] mainwindow.h
├── [1.2K] mainwindow.ui
└── [4.0K] qjson
├── [6.4K] CMakeLists.txt
├── [ 26K] COPYING.lib
├── [3.8K] ChangeLog
├── [ 195] QJSONConfig.cmake.in
├── [ 477] QJSONConfigVersion.cmake.in
├── [ 390] QJson.pc.in
├── [3.1K] README.license
├── [3.4K] README.md
├── [4.0K] build
├── [ 750] cmake_uninstall.cmake.in
├── [4.0K] doc
├── [4.0K] include
├── [4.0K] src
└── [4.0K] tests
3. 定义有动态列表的对象模型
- cncposition.h
#ifndef CNCPOSITION_H
#define CNCPOSITION_H
#include <QObject>
#include <QVector>
#include <QList>
#include <QStringList>
#include <QVariantList>
#include <QDebug>
class CncPosition : public QObject
{
Q_OBJECT
// Q_PROPERTY(int code READ code WRITE setCode)
// Q_PROPERTY(QString message READ message WRITE setMessage)
Q_PROPERTY(QStringList axis READ axis WRITE setAxis)
Q_PROPERTY(QStringList units READ units WRITE setUnits)
Q_PROPERTY(QVariant absoluteCoords READ absoluteCoords WRITE setAbsoluteCoords)
Q_PROPERTY(QVariant relativeCoords READ relativeCoords WRITE setRelativeCoords)
Q_PROPERTY(QVariant machineCoords READ machineCoords WRITE setMachineCoords)
Q_PROPERTY(QVariant distances READ distances WRITE setDistances)
public:
explicit CncPosition(QObject *parent = nullptr);
// int code() const { return _code; }
// void setCode(int code) { _code = code; }
// QString message() const { return _message; }
// void setMessage(QString &message) { _message = message; }
QStringList axis() const { return _axis; }
void setAxis(const QStringList &axis)
{
// qDebug() << axis;
_axis = axis;
}
QStringList units() const { return _units; }
void setUnits(const QStringList &units)
{
// qDebug() << units;
_units = units;
}
private:
QVariant absoluteCoords() const { return QVariant::fromValue(_absoluteCoords); }
QVariant relativeCoords() const { return QVariant::fromValue(_relativeCoords); }
QVariant machineCoords() const { return QVariant::fromValue(_machineCoords); }
QVariant distances() const { return QVariant::fromValue(_distances); }
public:
QList<double> getAbsoluteCoords() const { return _absoluteCoords; }
void setAbsoluteCoords(const QVariant &absoluteCoords)
{
_absoluteCoords.clear();
for (auto var: absoluteCoords.toList()) {
_absoluteCoords.append(var.toDouble());
}
}
QList<double> getRelativeCoords() const { return _relativeCoords; }
void setRelativeCoords(const QVariant &relativeCoords)
{
_relativeCoords.clear();
for (auto var : relativeCoords.toList()) {
_relativeCoords.append(var.toDouble());
}
}
QList<double> getMachineCoords() const {return _machineCoords;}
void setMachineCoords(const QVariant &machineCoords)
{
_machineCoords.clear();
for (auto var : machineCoords.toList()) {
_machineCoords.append(var.toDouble());
}
}
QList<double> getDistences() const {return _distances;}
void setDistances(const QVariant &distances)
{
_distances.clear();
for (auto var : distances.toList()) {
_distances.append(var.toDouble());
}
}
public:
friend QDebug operator<<(QDebug dbg, const CncPosition &p)
{
// dbg.nospace() << "code:" << p.code() << "message:" << p.message()
// << "Axis:" << p.Axis() << "Units:" << p.Units() << "AbsoluteCoords:" << p.AbsoluteCoords()
// << "RelativeCoords:" << p.RelativeCoords() << "MachineCoords:" << p.MachineCoords()
// << "Distances:" << p.Distances();
// dbg << "code:" << p.code() << "message:" << p.message()
dbg << "Axis:" << p.axis() << "Units:" << p.units() << "AbsoluteCoords:" << p.getAbsoluteCoords()
<< "RelativeCoords:" << p.getRelativeCoords() << "MachineCoords:" << p.getMachineCoords()
<< "Distances:" << p.getDistences();
return dbg;
}
signals:
private:
// int _code;
// QString _message;
QStringList _axis;
QStringList _units;
QList<double> _absoluteCoords;
QList<double> _relativeCoords;
QList<double> _machineCoords;
QList<double> _distances;
};
#endif // CNCPOSITION_H
4. 运行验证
在mainwindow这个Widget中定义了一个PushButtton和一个用于显示请求到的application/json;charset=utf-8的Content-Type, 下面时验证代码,将QNetworkAccessManager使用同步的方式取结果
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, [=]
{
std::unique_ptr<QNetworkAccessManager> manager = std::make_unique<QNetworkAccessManager>(new QNetworkAccessManager());
QUrlQuery urlQuery;
urlQuery.addQueryItem("fcode", "CNC_POSITION");
QUrl url("http://127.0.0.1:9001/das/services/pull?" + urlQuery.query(QUrl::FullyDecoded));
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/json;charset=utf-8");
QNetworkReply *reply = manager->get(request);
QEventLoop eloop;
QObject::connect(reply, &QNetworkReply::finished, &eloop, &QEventLoop::quit);
eloop.exec(QEventLoop::ExcludeUserInputEvents);
auto jstr = reply->readAll();
// QString text = "{\"axis\":[\"X\",\"Y\",\"Z\",\"A\",\"U\"],\"units\":[\"mm\",\"mm\",\"mm\",\"ang\",\"mm\"],\"absoluteCoords\":[33,-768,98.7,99,0],\"relativeCoords\":[33,-768,98.7,99,0],\"machineCoords\":[33,-768,98.7,99,0],\"distances\":[0,0,0,0,0]}";
QJson::Parser parser;
parser.specialNumbersAllowed();
bool ok = false;
auto variant = parser.parse(jstr, &ok);
// auto variant = parser.parse(text.toUtf8(), &ok);
if (!ok)
{
qWarning() << parser.errorString();
return;
}
// 返回值检查
auto map = variant.toMap();
int code = map["code"].toInt();
if (code != 0)
{
qWarning() << map["message"].toString();
return;
}
// 反序列化到对象实列
CncPosition position;
QJson::QObjectHelper::qvariant2qobject(map["data"].toMap(), &position);
qDebug() << position;
ui->textEdit->setText(jstr);
reply->deleteLater(); });
}
后端返回的Json内容如下
{"code":0,"message":"成功","data":{"axis":["X","Y","Z","A","U"],"units":
["mm","mm","mm","ang","mm"],"absoluteCoords":
[33,-768,98.7,99,0],"relativeCoords":[33,-768,98.7,99,0],"machineCoords":
[33,-768,98.7,99,0],"distances":[0,0,0,0,0]}}
最终执行程序验证,通过cncpostion类中重载的<<操作符,输出结果
Axis: ("X", "Y", "Z", "A", "U") Units: ("mm", "mm", "mm", "ang", "mm")
AbsoluteCoords: (33, -768, 98.7, 99, 0) RelativeCoords: (33, -768, 98.7, 99, 0) MachineCoords: (33, -768, 98.7, 99, 0) Distances: (0, 0, 0, 0, 0)
5. 结论
- QJson来进行对象的序列、反序列化非常的方便,提高了程序的可读性与开发效率
- 服务端序列化Key值使用小驼峰方式,二者之间必须明确协议,服务端能够兼容到不区分大小写的Key值,通过实际使用中发现QJson对Key值大小写敏感,否则QJson::QObjectHelper::qvariant2qobject会失败
- 能注意到cncpostion中Q_PROPERTY的部分的操作类型必须保持一致,否则Qt Moc(Meta-Object Compiler)会出错,但是Moc并不会限制READ、WRITE部分的访问权限,猜测是做的模板生成与字符方面的处理,这样可以让需要序列、反序列部分使用QJson解析支持的QVariant, 然后公开出去的Get属性返回最终的使用类型。
本文福利,莬费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击莬费领取↓↓