当前位置: 首页 > news >正文

用观察者模式通知UI刷新数据

用观察者模式用UI显示数据变化

  • 主程序
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
#include "Observer.h"
#include <QDebug>class UIObserver : public Observer {
public:void Execute() override { qDebug() << "[UI] refresh"; }
};class IoObserver : public Observer {
public:void Execute() override{qDebug() << "[IO] flush";}
};int main(int argc, char *argv[])
{QApplication app(argc, argv);auto& m = Model::GetInstance();std::shared_ptr<QtWidgetsApplication1> window = std::make_shared<QtWidgetsApplication1>();std::shared_ptr<UIObserver> UI = std::make_shared<UIObserver>();std::shared_ptr<IoObserver> OI = std::make_shared<IoObserver>();int64_t h1 = m.Register(UI);int64_t h2 = m.Register(OI);int64_t h3 = m.Register(window);window->show();return app.exec();
}
  • 逻辑UI
#pragma once#include <QtWidgets/QWidget>
#include "ui_QtWidgetsApplication1.h"
#include "Observer.h"class QtWidgetsApplication1 : public QWidget, public Observer
{Q_OBJECTpublic:QtWidgetsApplication1(QWidget *parent = nullptr);~QtWidgetsApplication1();void Execute() override;public slots:void onUpdate();void doUpdate(int v); // 在主线程执行private:Ui::QtWidgetsApplication1Class ui;int m_nCounter = 1;
};
#include "QtWidgetsApplication1.h"
#include <QPushButton>
#include <QThread>
#include <QDebug>QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent): QWidget(parent)
{ui.setupUi(this);connect(ui.btnUpdate, &QPushButton::clicked, this, &QtWidgetsApplication1::onUpdate);qDebug() << "Main thread ID: " << QThread::currentThreadId();
}QtWidgetsApplication1::~QtWidgetsApplication1()
{}void QtWidgetsApplication1::onUpdate()
{Model::GetInstance().Notify();
}void QtWidgetsApplication1::Execute()
{qDebug() << "Current thread ID: " << QThread::currentThreadId();if (thread() != QThread::currentThread()){QMetaObject::invokeMethod(this,"doUpdate",Qt::QueuedConnection,Q_ARG(int, m_nCounter++));}else{doUpdate(m_nCounter++);}
}void QtWidgetsApplication1::doUpdate(int v)
{if (thread() != QThread::currentThread()){qFatal("Execute is NOT in GUI thread!");}ui.lblValue->setText(QString::number(v));
}
  • 模式设计
#pragma once
#include <queue>
#include <mutex>
#include <thread>
#include <memory>
#include <vector>class Observer
{
public:virtual ~Observer() = default;virtual void Execute() = 0;
};using ObserverPtr = std::shared_ptr<Observer>;
using WeakObserverPtr = std::weak_ptr<Observer>;class Model
{
public:virtual ~Model();static Model& GetInstance(){static Model model;return model;}/*-----增*删*改*查-----*/int64_t Register(ObserverPtr sp);		// 返回句柄,用于注销void Unregister(int64_t handle);		// 删除void Notify();							// 异步通知(非阻塞)void NotifySync();						// 同步通知private:Model();struct Slot{int64_t handle;WeakObserverPtr wptr;};std::vector<Slot>			m_slots;std::mutex					m_mtx;int64_t						m_nextHandle	= 1;/*-----异步通知线程-----*/void Worker();std::thread					m_worker;std::queue<int64_t>			m_taskQueue;std::condition_variable		m_cv;bool						m_stop			= false;
};
#include "Observer.h"
#include <iostream>int64_t Model::Register(ObserverPtr sp)
{std::lock_guard<std::mutex> lock(m_mtx);m_slots.push_back({ m_nextHandle, sp });return m_nextHandle++;
}void Model::Unregister(int64_t handle)
{std::lock_guard<std::mutex> lock(m_mtx);m_slots.erase(std::remove_if(m_slots.begin(), m_slots.end(),[=](const Slot& s) {return s.handle == handle; }),m_slots.end());
}// 同步通知(立即执行,会阻塞调用者)
void Model::NotifySync()
{std::lock_guard<std::mutex> lock(m_mtx);for (auto it = m_slots.begin(); it != m_slots.end();){if (auto sp = it->wptr.lock()){sp->Execute();++it;}else{it = m_slots.erase(it);}}
}// 异步通知(把任务抛给后台线程,调用者立即返回)
void Model::Notify()
{{std::lock_guard<std::mutex> lock(m_mtx);m_taskQueue.push(-1); // -1 代表“通知全部”}m_cv.notify_one();
}// 后台worker真正遍历并调用
void Model::Worker()
{while (true){std::unique_lock<std::mutex> lock(m_mtx);m_cv.wait(lock, [this] {return !m_taskQueue.empty() || m_stop; });if (m_stop){break;}auto todo = std::move(m_taskQueue);lock.unlock();while (!todo.empty()){int64_t cmd = todo.front();todo.pop();lock.lock();for (auto& s : m_slots){if (auto sp = s.wptr.lock()){sp->Execute();}}lock.unlock();}}
}Model::Model() :m_worker(&Model::Worker, this) {}Model::~Model()
{{std::lock_guard<std::mutex> lock(m_mtx);m_stop = true;m_cv.notify_all();}m_worker.join();
}
http://www.dtcms.com/a/494409.html

相关文章:

  • 基于 AI 大模型的 UI 元素定位浏览器插件
  • Prism框架核心对象全解析
  • 阿里云服务器上部署Mosquitto
  • Android 设计模式实战手册(Kotlin 实战版)
  • Android thermal (5)_cooling device(下)
  • 活字格低代码平台实现移动端应用(安卓 /iOS)打包的技术方案与实践指南
  • SpringBoot电子商城系统
  • 解析 Qt Remote Objects:从框架原理到 Repcs 实践,以正点原子 RK3588 UI 系统为例
  • 【底层机制】【Android】Binder架构与原理
  • 揭阳市住房和城乡建设局网站网站类游戏网站开发
  • DeviceNet 转 MODBUS TCP罗克韦尔 ControlLogix PLC 与上位机在汽车零部件涂装生产线漆膜厚度精准控制的通讯配置案例
  • 【STM32项目开源】基于STM32的智能衣柜系统
  • python基于web的汽车班车车票管理系统/火车票预订系统/高铁预定系统 可在线选座
  • ssh终端管理多个k8s集群,快速切换配置
  • 景德镇建站公司全国建筑四库一平台
  • 奥运网站模板wordpress在 分栏
  • toLua[七] Examples 06_LuaCoroutine2分析
  • CAD如何生成等高线
  • Java并发工具类详解:Semaphore、CyclicBarrier与CountDownLatch
  • 御剑问情_附带自动假人版_大型3D仙侠类剧情闯关手游_Linux服务端_通用视频架设教程_GM授权网页后台_运营网页后台_安卓苹果IOS双端
  • 基于信息保留与细粒度特征聚合的无人机目标检测
  • AINode部署全指南:从独立部署到Kubernetes集群部署
  • PYcharm——获取天气
  • Kafka多网卡环境配置
  • TypeScript 与淘宝 API:构建类型安全的商品数据查询前端 / Node.js 服务
  • 网站备案名称要求郴州网站排名优化
  • 百度做一个网站多少钱sns营销
  • List<map<String,Object>下划线转驼峰
  • List.subList() 返回值为什么不能强转成 ArrayList
  • phpcms网站转移网站关键词百度排名在下降