文章的目的为了记录使用C++ 进行QT Widget 开发学习的经历。临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
开源 C++ QT Widget 开发(一)工程文件结构-CSDN博客
开源 C++ QT Widget 开发(二)基本控件应用-CSDN博客
开源 C++ QT Widget 开发(三)图表--波形显示器-CSDN博客
开源 C++ QT Widget 开发(四)文件--二进制文件查看编辑-CSDN博客
开源 C++ QT Widget 开发(五)通讯--串口调试-CSDN博客
开源 C++ QT Widget 开发(六)通讯--TCP调试-CSDN博客
开源 C++ QT Widget 开发(七)线程--多线程及通讯-CSDN博客
开源 C++ QT Widget 开发(八)网络--Http文件下载-CSDN博客
开源 C++ QT Widget 开发(九)图表--仪表盘-CSDN博客
推荐链接:
开源 java android app 开发(一)开发环境的搭建-CSDN博客
开源 java android app 开发(二)工程文件结构-CSDN博客
开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客
开源 java android app 开发(四)GUI界面重要组件-CSDN博客
开源 java android app 开发(五)文件和数据库存储-CSDN博客
开源 java android app 开发(六)多媒体使用-CSDN博客
开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客
开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客
开源 java android app 开发(九)后台之线程和服务-CSDN博客
开源 java android app 开发(十)广播机制-CSDN博客
开源 java android app 开发(十一)调试、发布-CSDN博客
开源 java android app 开发(十二)封库.aar-CSDN博客
推荐链接:
开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客
开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客
本章主要内容:Qt 的共享内存 (QSharedMemory) 实现的进程间通信 (IPC) 应用程序。
目录:
1.主要功能
2.源码分析
3.所有源码
4.效果演示
一、主要功能
这个应用程序实现了两个进程间通过共享内存进行通信的功能:
发送消息:将文本消息写入共享内存
接收消息:从共享内存读取消息并显示
自动检测:定时检查共享内存中是否有新消息
二、源码分析
1. Mainwindow.h文件
使用 QSharedMemory 实现共享内存功能
使用 QTimer 定期检查共享内存
定义了三个主要槽函数对应按钮点击事件
包含共享内存设置和状态更新方法
2. Mainwindow.cpp文件
setupSharedMemory():
尝试创建共享内存(如果不存在)
如果已存在则附加到现有共享内存
处理创建/附加失败的情况
on_sendButton_clicked():
检查并附加到共享内存
将消息和时间戳序列化到缓冲区
锁定共享内存并复制数据
更新状态并清空输入框
on_receiveButton_clicked():
从共享内存读取数据
反序列化消息和时间戳
格式化并显示接收到的消息
checkSharedMemory():
定时检查共享内存中是否有新消息
有消息时更新状态标签的样式提示用户
updateStatus():
更新状态标签并设置临时样式
3秒后恢复默认状态
三、所有源码
1. mianwindow.h文件
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSharedMemory>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_sendButton_clicked();
void on_receiveButton_clicked();
void on_clearButton_clicked();
void checkSharedMemory();
private:
Ui::MainWindow *ui;
QSharedMemory *sharedMemory;
QTimer *checkTimer;
void setupSharedMemory();
void updateStatus(const QString &message);
};
#endif // MAINWINDOW_H
2. mainwindow.cpp文件
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBuffer>
#include <QDataStream>
#include <QMessageBox>
#include <QDateTime>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, sharedMemory(new QSharedMemory("MyAppSharedMemory", this))
{
ui->setupUi(this);
// 设置界面初始状态
ui->statusLabel->setText("就绪");
ui->statusLabel->setStyleSheet("QLabel { background-color: lightgray; padding: 5px; }");
// 设置共享内存
setupSharedMemory();
// 创建定时器定期检查共享内存
checkTimer = new QTimer(this);
connect(checkTimer, &QTimer::timeout, this, &MainWindow::checkSharedMemory);
checkTimer->start(1000); // 每秒检查一次
// 设置初始消息
ui->messageEdit->setText("你好,这是来自QT共享内存的消息!");
}
MainWindow::~MainWindow()
{
// 清理共享内存
if (sharedMemory->isAttached()) {
sharedMemory->detach();
}
delete ui;
}
void MainWindow::setupSharedMemory()
{
// 尝试创建或附加到共享内存
if (!sharedMemory->create(1024) && sharedMemory->error() == QSharedMemory::AlreadyExists) {
if (sharedMemory->attach()) {
updateStatus("已连接到现有共享内存");
} else {
updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
}
} else if (sharedMemory->isAttached()) {
updateStatus("已创建新的共享内存");
} else {
updateStatus("无法创建共享内存: " + sharedMemory->errorString());
}
}
void MainWindow::on_sendButton_clicked()
{
if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
return;
}
QString message = ui->messageEdit->text();
if (message.isEmpty()) {
QMessageBox::warning(this, "警告", "消息不能为空!");
return;
}
// 准备数据
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
// 写入消息和时间戳
out << message;
out << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
// 写入共享内存
sharedMemory->lock();
char *to = static_cast<char*>(sharedMemory->data());
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory->size(), static_cast<int>(buffer.size())));
sharedMemory->unlock();
updateStatus("消息已发送到共享内存: " + message);
ui->messageEdit->clear();
}
void MainWindow::on_receiveButton_clicked()
{
if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
updateStatus("无法附加到共享内存: " + sharedMemory->errorString());
return;
}
// 从共享内存读取数据
sharedMemory->lock();
QByteArray byteArray(static_cast<const char*>(sharedMemory->constData()), sharedMemory->size());
sharedMemory->unlock();
QBuffer buffer(&byteArray);
buffer.open(QBuffer::ReadOnly);
QDataStream in(&buffer);
QString message;
QString timestamp;
in >> message >> timestamp;
if (message.isEmpty()) {
ui->receivedTextEdit->append("没有可用的消息");
} else {
QString displayText = QString("[%1] %2").arg(timestamp, message);
ui->receivedTextEdit->append(displayText);
updateStatus("收到新消息: " + message);
}
}
void MainWindow::on_clearButton_clicked()
{
ui->receivedTextEdit->clear();
updateStatus("已清除接收的消息");
}
void MainWindow::checkSharedMemory()
{
// 定期检查共享内存中是否有新数据
if (!sharedMemory->isAttached() && !sharedMemory->attach()) {
return;
}
sharedMemory->lock();
QByteArray byteArray(static_cast<const char*>(sharedMemory->constData()), sharedMemory->size());
sharedMemory->unlock();
QBuffer buffer(&byteArray);
buffer.open(QBuffer::ReadOnly);
QDataStream in(&buffer);
QString message;
QString timestamp;
in >> message >> timestamp;
if (!message.isEmpty()) {
// 更新状态提示有新消息
ui->statusLabel->setText("有新消息可用!");
ui->statusLabel->setStyleSheet("QLabel { background-color: lightgreen; padding: 5px; }");
}
}
void MainWindow::updateStatus(const QString &message)
{
ui->statusLabel->setText(message);
ui->statusLabel->setStyleSheet("QLabel { background-color: lightblue; padding: 5px; }");
// 3秒后恢复普通状态
QTimer::singleShot(3000, this, [this]() {
ui->statusLabel->setText("就绪");
ui->statusLabel->setStyleSheet("QLabel { background-color: lightgray; padding: 5px; }");
});
}
3. mainwindow.ui文件
在工程文件夹下用记事本打开
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>QT共享内存IPC示例</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>发送消息:</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="messageEdit"/>
</item>
<item>
<widget class="QPushButton" name="sendButton">
<property name="text">
<string>发送</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>接收的消息:</string>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="receivedTextEdit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="receiveButton">
<property name="text">
<string>接收消息</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clearButton">
<property name="text">
<string>清除</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="statusLabel"/>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>
四、效果演示
输入消息
发送消息
接收消息