文章的目的为了记录使用QT QML开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
开源 C++ QT QML 开发(四)复杂控件--Listview
开源 C++ QT QML 开发(五)复杂控件--Gridview
推荐链接:
开源 C# 快速开发(十六)数据库--sqlserver增删改查
本章节主要内容是:使用进程进行进程的监控,进程调用,命令的执行,演示进程的作用。
1.代码分析
2.所有源码
3.效果演示
一、代码分析
二、所有源码
三、效果演示
可以显示当前进程,打开记事本,执行dir命令,演示进程的三种功能。
- C++ 后台代码分析
ProcessManager 类头文件 (processmanager.h)
class ProcessManager : public QObject
{
Q_OBJECT // Qt的元对象系统宏,启用信号槽机制
作用:继承自QObject,使类能够使用Qt的信号槽机制
构造函数
explicit ProcessManager(QObject *parent = nullptr) : QObject(parent) {}
作用:简单的构造函数,调用父类QObject的构造函数
showCurrentProcess() 函数
void showCurrentProcess()
{
qDebug() << "当前进程PID:" << QCoreApplication::applicationPid();
emit processInfoReady("当前进程PID: " + QString::number(QCoreApplication::applicationPid()));
}
详细分析:
QCoreApplication::applicationPid():获取当前应用程序的进程ID
qDebug():在控制台输出调试信息
emit processInfoReady():发射信号,将信息传递到QML界面
功能:显示当前Qt应用程序自身的进程ID
openNotepad() 函数
void openNotepad()
{
QProcess *process = new QProcess(this); // 创建QProcess对象,this指定父对象用于自动内存管理
// 连接进程结束信号到lambda表达式
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[process](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "记事本进程结束,退出码:" << exitCode;
process->deleteLater(); // 安全删除进程对象
});
#ifdef Q_OS_WIN
process->start("notepad.exe"); // Windows系统启动记事本
#else
process->start("gedit"); // Linux系统启动gedit
#endif
if (process->waitForStarted()) { // 等待进程启动,超时时间默认30秒
emit processInfoReady("记事本已启动");
} else {
emit processInfoReady("启动记事本失败");
}
}
详细分析:
QProcess *process = new QProcess(this):创建进程对象,指定父对象实现自动内存管理
connect(... finished ...):连接进程结束信号,使用lambda表达式处理
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished):处理重载信号的正确连接方式
process->deleteLater():在事件循环中安全删除对象
预处理指令 #ifdef Q_OS_WIN:实现跨平台兼容
process->start():启动外部程序
process->waitForStarted():阻塞等待进程启动,返回布尔值表示是否成功
executeDirCommand() 函数
void executeDirCommand()
{
QProcess *process = new QProcess(this);
// 连接标准输出信号
connect(process, &QProcess::readyReadStandardOutput, [process, this]() {
QString output = QString::fromLocal8Bit(process->readAllStandardOutput());
emit commandOutputReady(output);
});
// 连接标准错误信号
connect(process, &QProcess::readyReadStandardError, [process, this]() {
QString error = QString::fromLocal8Bit(process->readAllStandardError());
emit commandOutputReady("错误: " + error);
});
// 连接进程结束信号
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[process, this](int exitCode, QProcess::ExitStatus exitStatus) {
emit commandOutputReady("\n命令执行完成,退出码: " + QString::number(exitCode));
process->deleteLater();
});
#ifdef Q_OS_WIN
process->start("cmd", QStringList() << "/c" << "dir"); // Windows执行dir命令
#else
process->start("ls", QStringList() << "-l"); // Linux执行ls -l命令
#endif
if (!process->waitForStarted()) {
emit commandOutputReady("启动命令失败");
}
}
详细分析:
readyReadStandardOutput:当进程有标准输出时触发
readyReadStandardError:当进程有错误输出时触发
readAllStandardOutput():读取所有标准输出数据
QString::fromLocal8Bit():将本地8位编码转换为QString
QStringList() << "/c" << "dir":创建参数列表,/c表示执行后终止cmd
使用三个独立的connect来分别处理输出、错误和结束事件
信号声明
signals:
void processInfoReady(const QString &info);
void commandOutputReady(const QString &output);
作用:定义两个信号,用于C++到QML的通信
-
main.cpp 分析
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 启用高DPI缩放
QGuiApplication app(argc, argv); // 创建GUI应用程序对象ProcessManager processManager; // 创建进程管理器实例 QQmlApplicationEngine engine; // 创建QML引擎 // 将C++对象注册为QML上下文属性 engine.rootContext()->setContextProperty("processManager", &processManager); // 从qrc资源文件加载QML engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) // 检查QML是否加载成功 return -1; return app.exec(); // 进入主事件循环
}
-
QML 界面详细分析
ApplicationWindow
ApplicationWindow {
id: window
width: 800
height: 600
visible: true
title: "Qt进程管理示例"
作用:创建主应用程序窗口
背景渐变
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: "#2c3e50" }
GradientStop { position: 1.0; color: "#3498db" }
}
}
作用:创建从深蓝色到浅蓝色的垂直渐变背景
按钮组件分析
Button {
Layout.fillWidth: true
text: "显示当前进程"
font.pixelSize: 16
background: Rectangle {
color: parent.down ? "#27ae60" : "#2ecc71" // 按下时变深色
radius: 8 // 圆角
}
contentItem: Text {
text: parent.text
font: parent.font
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
processManager.showCurrentProcess() // 调用C++函数
}
}
详细分析:
Layout.fillWidth: true:在布局中填充宽度
background:自定义按钮背景,实现按下状态颜色变化
contentItem:自定义按钮文本样式
onClicked:按钮点击事件处理器,调用C++函数
输出显示区域
ScrollView {
anchors.fill: parent
anchors.margins: 5
TextArea {
id: outputArea
readOnly: true // 只读
wrapMode: Text.Wrap // 自动换行
color: "#ecf0f1" // 文字颜色
font.pixelSize: 12
font.family: "Courier New" // 等宽字体,适合显示命令输出
background: null // 透明背景
placeholderText: "命令输出将显示在这里..."
}
}
Connections 组件
Connections {
target: processManager // 连接的C++对象
onProcessInfoReady: { // 处理processInfoReady信号
infoArea.text = info + "\n" + infoArea.text // 新信息添加到顶部
}
onCommandOutputReady: { // 处理commandOutputReady信号
outputArea.text = output + outputArea.text
}
}
作用:建立C++信号到QML的连接,实现数据传递
二、所有源码
processmanager .h文件源码
#ifndef PROCESSMANAGER_H
#define PROCESSMANAGER_H
#include <QObject>
#include <QProcess>
#include <QDebug>
#include <QCoreApplication>
class ProcessManager : public QObject
{
Q_OBJECT
public:
explicit ProcessManager(QObject *parent = nullptr) : QObject(parent) {}
public slots:
// 显示当前进程信息
void showCurrentProcess()
{
qDebug() << "当前进程PID:" << QCoreApplication::applicationPid();
emit processInfoReady("当前进程PID: " + QString::number(QCoreApplication::applicationPid()));
}
// 打开记事本
void openNotepad()
{
QProcess *process = new QProcess(this);
// 进程结束时自动删除
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[process](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "记事本进程结束,退出码:" << exitCode;
process->deleteLater();
});
#ifdef Q_OS_WIN
process->start("notepad.exe");
#else
process->start("gedit"); // Linux系统使用gedit
#endif
if (process->waitForStarted()) {
emit processInfoReady("记事本已启动");
} else {
emit processInfoReady("启动记事本失败");
}
}
// 执行cmd dir命令
void executeDirCommand()
{
QProcess *process = new QProcess(this);
connect(process, &QProcess::readyReadStandardOutput, [process, this]() {
QString output = QString::fromLocal8Bit(process->readAllStandardOutput());
emit commandOutputReady(output);
});
connect(process, &QProcess::readyReadStandardError, [process, this]() {
QString error = QString::fromLocal8Bit(process->readAllStandardError());
emit commandOutputReady("错误: " + error);
});
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[process, this](int exitCode, QProcess::ExitStatus exitStatus) {
emit commandOutputReady("\n命令执行完成,退出码: " + QString::number(exitCode));
process->deleteLater();
});
#ifdef Q_OS_WIN
process->start("cmd", QStringList() << "/c" << "dir");
#else
process->start("ls", QStringList() << "-l"); // Linux系统使用ls -l
#endif
if (!process->waitForStarted()) {
emit commandOutputReady("启动命令失败");
}
}
signals:
void processInfoReady(const QString &info);
void commandOutputReady(const QString &output);
};
#endif // PROCESSMANAGER_H
main.qml文件源码
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
ApplicationWindow {
id: window
width: 800
height: 600
visible: true
title: "Qt进程管理示例"
// 背景渐变
Rectangle {
anchors.fill: parent
gradient: Gradient {
GradientStop { position: 0.0; color: "#2c3e50" }
GradientStop { position: 1.0; color: "#3498db" }
}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 20
spacing: 15
// 标题
Text {
Layout.alignment: Qt.AlignHCenter
text: "进程管理演示"
font.pixelSize: 28
font.bold: true
color: "white"
}
// 按钮区域
RowLayout {
Layout.fillWidth: true
spacing: 15
// 显示当前进程按钮
Button {
Layout.fillWidth: true
text: "显示当前进程"
font.pixelSize: 16
background: Rectangle {
color: parent.down ? "#27ae60" : "#2ecc71"
radius: 8
}
contentItem: Text {
text: parent.text
font: parent.font
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
processManager.showCurrentProcess()
}
}
// 打开记事本按钮
Button {
Layout.fillWidth: true
text: "打开记事本"
font.pixelSize: 16
background: Rectangle {
color: parent.down ? "#2980b9" : "#3498db"
radius: 8
}
contentItem: Text {
text: parent.text
font: parent.font
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
processManager.openNotepad()
}
}
// 执行Dir命令按钮
Button {
Layout.fillWidth: true
text: "执行Dir命令"
font.pixelSize: 16
background: Rectangle {
color: parent.down ? "#c0392b" : "#e74c3c"
radius: 8
}
contentItem: Text {
text: parent.text
font: parent.font
color: "white"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
onClicked: {
processManager.executeDirCommand()
outputArea.text = "执行命令中..."
}
}
}
// 信息显示区域
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 100
color: "#34495e"
radius: 8
border.color: "#7f8c8d"
border.width: 2
ScrollView {
anchors.fill: parent
anchors.margins: 5
TextArea {
id: infoArea
readOnly: true
wrapMode: Text.Wrap
color: "#ecf0f1"
font.pixelSize: 14
background: null
placeholderText: "进程信息将显示在这里..."
}
}
}
// 命令输出区域
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
color: "#2c3e50"
radius: 8
border.color: "#7f8c8d"
border.width: 2
ScrollView {
anchors.fill: parent
anchors.margins: 5
TextArea {
id: outputArea
readOnly: true
wrapMode: Text.Wrap
color: "#ecf0f1"
font.pixelSize: 12
font.family: "Courier New"
background: null
placeholderText: "命令输出将显示在这里..."
}
}
}
// 状态栏
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 30
color: "#1abc9c"
radius: 5
Text {
anchors.centerIn: parent
text: "Qt 5.12 进程管理示例 - 使用QProcess类"
color: "white"
font.pixelSize: 12
}
}
}
// 连接C++信号到QML
Connections {
target: processManager
onProcessInfoReady: {
infoArea.text = info + "\n" + infoArea.text
}
onCommandOutputReady: {
outputArea.text = output + outputArea.text
}
}
}
main.cpp文件源码
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "processmanager.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
// 注册进程管理器到QML
ProcessManager processManager;
QQmlApplicationEngine engine;
// 将C++对象暴露给QML
engine.rootContext()->setContextProperty("processManager", &processManager);
// 加载QML文件
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
三、效果演示
