首页 > 其他分享 >QAbstractEventDispatcher 抽象事件分发类

QAbstractEventDispatcher 抽象事件分发类

时间:2023-05-14 18:45:15浏览次数:40  
标签:分发 定时器 int void bucket 抽象 事件 QAbstractEventDispatcher

 

QAbstractEventDispatcher

QAbstractEventDispatcher 是一个抽象事件分发类,提供了一个事件循环,并将事件分发给相应的对象。

主要职责有:

1.管理一个事件循环,接收各种事件并分发

2.提供注册,注销事件等接口

3.处理定时器,到期后触发timeout 信号

4.处理异步信号连接,将其包装为事件进行分发

QAbstractEventDispatcher是一个抽象事件分发器类。它的主要作用是:
1. 管理定时器
2. 分发事件
3. 允许自定义事件过滤器
它定义了事件分发器的基本接口,而将具体实现留给子类。这个类使用了抽象工厂模式和模板方法模式。
主要成员函数包括:
1. registerTimer() - 注册定时器
2. unregisterTimer() - 删除定时器
3. registerSocketNotifier() - 注册socket通知器
4. unregisterSocketNotifier() - 删除socket通知器
5. processEvents() - 分发事件,这是一个模板方法
6. setEventFilter() - 设置自定义事件过滤器
7. filterEvent() - 根据事件过滤器过滤事件
这个类描述了Qt事件分发的基本框架,而具体实现与平台相关的代码在子类中实现。这使得整个设计具有很好的可扩展性与跨平台性。

 

//QAbstractEventDispatcher 的私有实现类,
class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
{
  Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
public:
  inline QAbstractEventDispatcherPrivate()
      : event_filter(0)
  { }
  void init();
  QAbstractEventDispatcher::EventFilter event_filter;//事件过滤器,用于过滤事件

  static int allocateTimerId(); //分配定时器id
  static void releaseTimerId(int id); //释放定时器id
};

 

//事件分发器的抽象基类,定义了事件分发器的公共接口,并提供了部分默认实现
class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject
{
  Q_OBJECT
  Q_DECLARE_PRIVATE(QAbstractEventDispatcher)

public:
  typedef QPair<int, int> TimerInfo;

  explicit QAbstractEventDispatcher(QObject *parent = 0);
  ~QAbstractEventDispatcher();

  static QAbstractEventDispatcher *instance(QThread *thread = 0);
//处理事件
  virtual bool processEvents(QEventLoop::ProcessEventsFlags flags) = 0;
  //待处理事件
  virtual bool hasPendingEvents() = 0;
//注册/注销套接字监听器,抽象方法
  virtual void registerSocketNotifier(QSocketNotifier *notifier) = 0;
  virtual void unregisterSocketNotifier(QSocketNotifier *notifier) = 0;
//注册/注销定时器,部分实现
  int registerTimer(int interval, QObject *object);
  virtual void registerTimer(int timerId, int interval, QObject *object) = 0;
  virtual bool unregisterTimer(int timerId) = 0;
  virtual bool unregisterTimers(QObject *object) = 0;
  virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0;
//唤醒事件循环
  virtual void wakeUp() = 0;
  //中断事件循环
  virtual void interrupt() = 0;
  //刷新事件循环
  virtual void flush() = 0;
//开始事件循环,
  virtual void startingUp();
  //结束事件循环
  virtual void closingDown();
//设置事件过滤器
  typedef bool(*EventFilter)(void *message);
  EventFilter setEventFilter(EventFilter filter);
  //过滤事件
  bool filterEvent(void *message);

Q_SIGNALS:
  void aboutToBlock();
  void awake();

protected:
  QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &,
                            QObject *parent);
};
//用于准备一个带序列号的新定时器id
//新定时器id的低24位与旧定时器id的高7位组合,生成一个新的定时器id。
static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
{
  return (newId & 0x00FFFFFF) | ((oldId + 0x01000000) & 0x7f000000);
}
//定时器id计算出所在的bucket
//通过遍历BucketSize数组,获得第一个大于定时器id的bucket索引。
static inline int bucketOffset(int timerId)
{
  for (int i = 0; i < NumberOfBuckets; ++i) {
      if (timerId < BucketSize[i])
          return i;
      timerId -= BucketSize[i];
  }
  qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
  return -1;
}
//根据bucket和定时器id计算在bucket中的索引位置
//简单地将定时器id减去bucket的偏移量BucketOffset[bucket]
static inline int bucketIndex(int bucket, int timerId)
{
  return timerId - BucketOffset[bucket];
}
//分配一个新的bucket。
//它根据bucket大小在堆上分配一个数组,并将每个元素初始化为该bucket下一个可用定时器id。
static inline int *allocateBucket(int bucket)
{
  // allocate a new bucket
  const int size = BucketSize[bucket];
  const int offset = BucketOffset[bucket];
  int *b = new int[size];
  for (int i = 0; i != size; ++i)
      b[i] = offset + i + 1;
  return b;
}

 

//初始化,将当前事件分发器实例和线程数据关联起来
void QAbstractEventDispatcherPrivate::init()
//分配一个定时器id,从可用定时器id中分配一个
int QAbstractEventDispatcherPrivate::allocateTimerId()
//释放一个定时器id
void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
//构造函数,析构函数
QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
  : QObject(*new QAbstractEventDispatcherPrivate, parent)
QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,QObject *parent)
QAbstractEventDispatcher::~QAbstractEventDispatcher()  

 

//构造单件模式,返回指定线程中的事件分发器
//在不同线程中获取对应的事件分发器对象,以便处理线程相关的事件循环
QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
//将定时器注册到事件分发器,
int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
//虚接口类:
void QAbstractEventDispatcher::startingUp()
void QAbstractEventDispatcher::closingDown()
//更新事件过滤器,返回原先的事件过滤器函数,而使用新的事件过滤器替代之
QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
//调用事件过滤器函数对事件进行过滤
bool QAbstractEventDispatcher::filterEvent(void *message)

标签:分发,定时器,int,void,bucket,抽象,事件,QAbstractEventDispatcher
From: https://www.cnblogs.com/wish-sleeping/p/17399862.html

相关文章

  • collection.abc模块下的抽象基类UML类图说明
    说明Iterable、Container和Sized每个容器都应该继承这三个抽象基类,或者实现兼容的协议。Iterable通过__iter__方法支持迭代,Container通过__contains__方法支持in运算符,Sized通过__len__方法支持len()函数。Collection这个抽象基类是3.6新增的,自身没有方法,目的是方便子类化I......
  • 接口继承和抽象类继承区别以及普通类和抽象类做基类的区别
    接口继承和抽象类继承区别C#中接口和抽象类都可以用于实现继承,但是它们有一些重要的区别。接口是一种行为规范,它只规定了类应该包括哪些方法,但是没有提供任何实现细节,因此实现接口的类必须提供所有规定的方法实现;抽象类是一种半成品类,它可以包含实现代码以及其他抽象方法,子类必......
  • 自学c#基础第七课,c#程序打包分发、textBox
    程序打包发布两种方式:1.解决方案右键生成解决方案,生成完成后打开所在路径找到debug文件夹下,压缩下debug所有文件,复制到别的电脑上即可使用。2.新建项目setup类型的,然后一步步设置,然后生成,生成后的文件是一个安装文件,自己复制到别的电脑上运行下,安装自己要的指定目录即可。textB......
  • 抽象工厂代码示例
    抽象工厂代码示例为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。产品族需要扩展的不适合抽象工厂,即在抽象工厂中在加一个createXXX();publicclassAbstractFactory{publicstaticvoidmain(String[]args){ComputerFactoryfactory......
  • 135. 分发糖果
    老师想给孩子们分发糖果,有N个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻的孩子中,评分高的孩子必须获得更多的糖果。那么这样下来,老师至少需要准备多少颗糖果呢?示例1:......
  • Java--抽象
    Java--抽象抽象的概念如果父类当中的方法不确定如何进行{}方法体的实现,那么这就应该是一个抽象方法抽象方法和抽象类的格式抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束.抽象类:抽象方法所在的类,必须是抽象类才行,在class之前写上abstract即可.代码示......
  • Python中的抽象类解说
    1、什么是抽象类?如果说,类是对一堆对象共同内容的抽取,那么抽象类就是对一堆类共同内容的抽取,包括:属性和方法。2、抽象类的特点(1)抽象类必须包含一个或多个抽象方法,也可以包含普通方法。(2)抽象类的抽象方法,在抽象类中并不作实现。(3)抽象类不能被实例(4)抽象类的子类要想进行实例化,必......
  • Java--抽象
    Java--抽象抽象的概念如果父类当中的方法不确定如何进行{}方法体的实现,那么这就应该是一个抽象方法抽象方法和抽象类的格式抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束.抽象类:抽象方法所在的类,必须是抽象类才行,在class之前写上abstract即可.代码示......
  • 接口与抽象类区别:
    1.接口(interface):1.是一种特殊的类文件(也是抽象类)2.作用: 制定一系列规则 降低耦合度 3.使用规则: 接口中属性,默认都是静态常量属性 接口中的方法都是抽象方法,如果需要重新定义具体方法实现, 此时方法需要使用default修饰 接口中的方法不是使用private修饰 接口与......
  • 【密码】量子密钥分发密钥率仿真附MATLAB代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......