qeventloop 事件循环类

QEventLoop

QEventLoop 是一个事件循环类,用来接收和分发事件的主循环,Qt中使用 事件循环来接收事件、信号和执行异步操作

class Q_CORE_EXPORT QEventLoop : public QObject
{
  Q_OBJECT
  Q_DECLARE_PRIVATE(QEventLoop)

public:
  explicit QEventLoop(QObject *parent = 0);
  ~QEventLoop();

  enum ProcessEventsFlag { //事件标志
      AllEvents = 0x00,
      ExcludeUserInputEvents = 0x01,
      ExcludeSocketNotifiers = 0x02,
      WaitForMoreEvents = 0x04,
#ifdef QT3_SUPPORT
      ExcludeUserInput = ExcludeUserInputEvents,
      WaitForMore = WaitForMoreEvents,
#endif
X11ExcludeTimers = 0x08
#ifdef QT_DEPRECATED
, DeferredDeletion = 0x10
#endif
      , EventLoopExec = 0x20
      , DialogExec = 0x40
  };
  Q_DECLARE_FLAGS(ProcessEventsFlags, ProcessEventsFlag)
//开启事件循环,可以传入 ProcessEventsFlags 过滤特定类型事件。
  bool processEvents(ProcessEventsFlags flags = AllEvents);
  //增加了一个最大时间参数,可以限制事件处理的最长时间。
  void processEvents(ProcessEventsFlags flags, int maximumTime);

  int exec(ProcessEventsFlags flags = AllEvents); //调用事件循环
  void exit(int returnCode = 0); //退出事件循环
  bool isRunning() const; //返回事件循环是否在运行

  void wakeUp(); //唤醒事件循环

public Q_SLOTS:
  void quit(); //退出时被调用
};
//QEventLoop 的私有实现类
class QEventLoopPrivate : public QObjectPrivate
{
  Q_DECLARE_PUBLIC(QEventLoop)
public:
  inline QEventLoopPrivate()
      : exit(true), inExec(false), returnCode(-1) //初始化 QEventLoop
  { }
  bool exit, inExec;
  int returnCode;
};
//构造函数,赋值d指针,创建事件分发器
QEventLoop::QEventLoop(QObject *parent)
  : QObject(*new QEventLoopPrivate, parent)
//将事件分发到线程的事件分发器,包含删除时,广播删除事件,在下次事件循环时手动回收资源
bool QEventLoop::processEvents(ProcessEventsFlags flags)
//调用 processEvents,使用 QTime 进行计时,超时 maxTime 退出
void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
//执行事件循环,一直调用 processEvents ,直到 exit为真退出
int QEventLoop::exec(ProcessEventsFlags flags)
//手动退出事件循环,设置退出值,中断事件分发器等待,让事件循环去检查 d—>exit 标记,退出 事件的exec
void QEventLoop::exit(int returnCode)
//返回事件 return !d->exit;
bool QEventLoop::isRunning() const
//唤醒事件分发器,
void QEventLoop::wakeUp()
//退出
void QEventLoop::quit()

应用举例:

#include <QCoreApplication>
#include <QThread>
#include <QDebug>

QEventLoop eventLoop;

// 工作线程
void workerThread()
{
  // 模拟工作线程执行任务
  qDebug() << "Worker thread started.";
  QThread::sleep(3);
  qDebug() << "Worker thread finished.";
// 条件满足时唤醒主线程
eventLoop.quit();
}
// 主线程中等待条件满足
int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
// 启动工作线程
QThread* thread = new QThread;
QObject::connect(thread, &QThread::started, workerThread);
thread->start();

// 等待条件满足
qDebug() << "Main thread waiting...";
eventLoop.exec(); //这里事件循环会阻塞直到 事件循环退出
qDebug() << "Main thread resumed.";

return a.exec();
}

 


cpp
// 下载管理器
class DownloadManager : public QObject
{
  Q_OBJECT
public:
  void addDownload(QUrl url); // 添加下载任务
private:
  QList<DownloadTask*> tasks; // 下载任务列表
};

// 单个下载任务
class DownloadTask : public QObject
{
  Q_OBJECT
public:
  DownloadTask(QUrl url);
  void run(); // 下载线程函数
private:
  QEventLoop *loop;     // 事件循环
  QNetworkAccessManager *manager; // 网络请求管理器
};

// 添加下载任务  
void DownloadManager::addDownload(QUrl url)
{
  // 创建下载任务
  DownloadTask *task = new DownloadTask(url);  
  tasks.append(task);
   
  // 将任务移动到新线程
  QThread *thread = new QThread();
  task->moveToThread(thread);
   
  // 连接信号槽,在线程启动后执行下载  
  connect(thread, &QThread::started, task, &DownloadTask::run);
   
  // 启动线程
  thread->start();
}

// 下载线程函数
void DownloadTask::run()
{
  // 创建事件循环
  loop = new QEventLoop();
   
  // 发起网络请求获取数据
  QNetworkReply *reply = manager->get(QNetworkRequest(url));
   
  // 在下载进度变化时,调用 wakeUp() 唤醒 GUI 线程  
  QObject::connect(reply, &QNetworkReply::downloadProgress,
                    [=](qint64 bytesReceived, qint64 bytesTotal) {
      updateProgress();     // 更新进度
      loop->wakeUp();     // 唤醒 GUI 线程
  });  
   
  // 执行事件循环,等待下载完成
  loop->exec();
}  

// 更新下载进度  
void DownloadTask::updateProgress()
{
  // 根据下载任务 id 更新 GUI 上的进度条
  emit progress(this->id, bytesReceived, bytesTotal);  
}


posted @   愿得入睡  阅读(1619)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示