Быстрый выпуск события (QuickEvent)
Примечание: при использовании Qt::AutoConnection, при публикации сообщения между потоками используется асинхронный запуск.
3.1.4. Приём и обработка сообщений
Для классов, которые вводят функции публикации и подписки, можно реализовать функцию обработки событий event_ + имя сообщения, чтобы принимать и обрабатывать отправленные сообщения publishEvent.
private slots:
void event_show_time(const QDateTime &time);
...
void Dialog::event_show_time(const QDateTime &time) {
box->setText(time.toString());
box->show();
}
Примечание: необходимо, чтобы списки параметров функций совпадали.
3.1.5. Отмена подписки
Класс QuickApplication предоставляет метод UnsubscribeEvent для отмены подписки на сообщения. Макрос QUICK_DESTRUCT позволяет легко отменять подписку.
Определение UnsubscribeEvent:
bool QuickApplication::UnsubscribeEvent(QObject *listener, QByteArray eventName) {
QWriteLocker loker(&s_lock);
bool result = false;
if(s_quick_event_pool.contains(eventName)) {
QMap<qint32, QObject *> tmplist = s_quick_event_pool[eventName];
tmplist.remove(tmplist.key(listener));
s_quick_event_pool.insert(eventName, tmplist);
result = true;
}
if(s_quick_event_pool_high.contains(eventName)) {
QMap<qint32, QObject *> tmplist = s_quick_event_pool[eventName];
tmplist.remove(tmplist.key(listener));
s_quick_event_pool.insert(eventName, tmlist);
result = true;
}
if(s_quick_event_pool_low.contains(eventName)) {
QMap<qint32, QObject *> tmplist = s_quick_event_pool[eventName];
tmplist.remove(tmplist.key(listener));
s_quick_event_pool.insert(eventName, tmlist);
result = true;
}
return result;
}
bool QuickApplication::UnsubscribeEvent(QObject *listener) {
QWriteLocker loker(&s_lock);
foreach (auto var, s_quick_event_pool.keys()) {
s_quick_event_pool[var].remove(s_quick_event_pool[var].key(listener));
}
foreach (auto var, s_quick_event_pool_low.keys()) {
s_quick_event_pool[var].remove(s_quick_event_pool[var].key(listener));
}
foreach (auto var, s_quick_event_pool_high.keys()) {
s_quick_event_pool[var].remove(s_quick_event_pool[var].key(listener));
}
return true;
}
Определение QUICK_DESTRUCT:
#define QUICK_DESTRUCT \
QuickApplication::UnsubscribeEvent(this);\
3.1.6. Приоритет подписки
По умолчанию, как и в случае с сигналами и слотами Qt, сообщения принимаются и обрабатываются в порядке подписки. Класс QuickEvent разделяет подписчиков на три категории: высокий уровень, по умолчанию и низкий уровень. После публикации сообщения все подписчики выполняются последовательно в порядке высокого уровня подписки, подписки по умолчанию и низкого уровня. При этом у подписчиков высокого и низкого уровней есть свой порядок, а у подписчиков по умолчанию порядка нет.
static QMap < QByteArray, QMap<qint32, QObject *> > s_quick_event_pool_high;
static QMap < QByteArray, QMap<qint32, QObject *> > s_quick_event_pool;
static QMap < QByteArray, QMap<qint32, QObject *> > s_quick_event_pool_low;
3.1.7. Типы публикации и подписки
При использовании QuickEvent поддерживается четыре режима публикации и подписки. Обратите внимание, что при использовании QuickEvent, как правило, неизвестно, какой код использует другая сторона. Будьте осторожны при использовании блокирующей публикации, чтобы избежать взаимоблокировки! 3.2. Контроль класса заполнения
Quick Event код модели предоставляет два управляющих класса: QuickWork, QuickScript.
3.2.1. QuickScript и его подклассы:
Наследуется от QThread скриптового базового класса, используется следующим образом:
Инициализация:
Выполнение:
Завершение:
Следует отметить: весь класс находится в новом потоке, за исключением метода Execute(), который находится в родительском потоке. Предоставляются интерфейсы Wait и Wake, которые можно использовать для вставки взаимодействия в расчёт скрипта, а также интерфейс SignalProgressIn для печати хода выполнения расчёта скрипта.
3.2.2. QuickWork и его подклассы:
Позволяет отражать себя через QUICK_AUT макрос и QuickController, что позволяет автоматически создавать экземпляры управляющих классов.
Класс QuickController используется для отражения и реализует автоматическое создание экземпляров QuickWork и его подклассов. Поток, к которому принадлежит QuickWork, может быть определён с помощью move_type.
QUICK_AUT макрос выполняет следующие функции:
Определение QUICK_AUTO:
#define QUICK_AUTO(ClassName)
Q_DECLARE_METATYPE(ClassName *)
static int ClassId##ClassName = qRegisterMetaType<ClassName *>();
static void *ThisPtr##ClassName = QuickController::NewInstance(#ClassName);
#define QUICK_AUTO_H(ClassName,value)
Q_DECLARE_METATYPE(ClassName *)
static int ClassId##ClassName = qRegisterMetaType<ClassName *>();
static void *ThisPtr##ClassName = QuickController::NewInstance(
#ClassName,QuickController::High,value);
#define QUICK_AUTO_L(ClassName,value)
Q_DECLARE_METATYPE(ClassName *)
static int ClassId##ClassName = qRegisterMetaType<ClassName *>();
static void *ThisPtr##ClassName = QuickController::NewInstance(
#ClassName,QuickController::Low,value);
Порядок отражения QuickWork и его подклассов аналогичен порядку подписки. Он делится на три уровня: высокий приоритет, по умолчанию, низкий приоритет. Сначала отражаются классы с высоким приоритетом, затем классы по умолчанию и, наконец, классы с низким приоритетом. В классе по умолчанию порядок не определён, в то время как в классах с высоким и низким приоритетом порядок определён.
Принцип заключается в том, что C/C++ не может выполнять сложные операции перед main, но можно выполнить часть кода перед main с использованием статических переменных и функций для присвоения значений. Однако эта операция может выполняться несколько раз, поэтому список отражённых классов использует контейнер Set для предотвращения дублирования вставок.
Примечание 1: после наследования от QuickWork можно переопределить метод QuickWork::start, который обязательно будет вызван в потоке назначения.
Примечание 2: если вставить повторяющиеся последовательности с высоким или низким приоритетом, будет выведено повторяющееся сообщение, и только один из них будет отражён.
3.3. Инициализация QuickEvent
Для использования только функции публикации и подписки QuickEvent нет необходимости инициализировать. Для управления классом отражения и жизненного цикла QuickEvent требуется инициализация в основной функции.
Макросы QUICK_INSTALL() и QUICK_INSTALL_DETAILED() могут использоваться для инициализации. QUICK_INSTALL_DETAILED() добавляет печать более подробной информации о QuickEvent, такой как версия, информация о деталях публикации и подписки, что удобно для отладки.
Пример:
#include "dialog.h"
#include <QuickEvent>
#include <QFile>
int main(int argc, char **argv) {
QApplication a(argc, argv);
QUICK_INSTALL()// QUICK_INSTALL QUICK_INSTALL_DETAIL
QUICK_SETSTYLE("../../Examples/resource/Style/gray_style.qss")
Dialog dialog;
dialog.show();
return a.exec();
}
3.4. Краткое описание всех макросов QuickEvent
Макрос QuickEvent | Описание |
---|---|
QUICK_AUTO(ClassName) | Регистрация типа в системе метаобъектов Qt и создание экземпляра самого себя (по умолчанию). |
QUICK_AUTO_H(ClassName, value) | Регистрация типа в системе метаобъектов Qt и создание экземпляра самого себя (высокий приоритет). |
QUICK_AUTO_L(ClassName, value) | Регистрация типа в системе метаобъектов Qt и создание экземпляра самого себя (низкий приоритет). |
QUICK_EVENT(PARENTNAME) | Позволяет классу поддерживать функции публикации и подписки. |
QUICK_DESTRUCT | Отменяет все подписки самого себя. |
QUICK_SUBSCRIBE_OBJ(obj, name) | Удобная подписка, подписчик и имя подписки (подписчик может быть собственной внутренней переменной). |
QUICK_SUBSCRIBE(name) | Простая подписка на себя. |
QUICK_SUBSCRIBE_H(name, lev) | Удобная высокая подписка на самого себя, lev указывает на сортировку высокой подписки, при повторении предыдущая удаляется. |
QUICK_SUBSCRIBE_L(name, lev) | Удобная низкая подписка на самого себя, lev указывает на сортировку низкой подписки, при повторении предыдущая удаляется. |
QUICK_PUBLISH1(name, arg1) | Публикация по умолчанию с одним параметром. |
QUICK_PUBLISH3(name,arg1,arg2,arg3) | режим публикации по умолчанию, 3 параметра |
QUICK_PUBLISH4(name,arg1,arg2,arg3,arg4) | режим публикации по умолчанию, 4 параметра |
QUICK_Direct_PUBLISH1(name,arg1) | синхронный режим публикации, 1 параметр |
QUICK_Direct_PUBLISH2(name,arg1,arg2) | синхронный режим публикации, 2 параметра |
QUICK_Direct_PUBLISH3(name,arg1,arg2,arg3) | синхронный режим публикации, 3 параметра |
QUICK_Queued_PUBLISH1(name,arg1) | асинхронный режим публикации, 1 параметр |
QUICK_Queued_PUBLISH2(name,arg1,arg2) | асинхронный режим публикации, 2 параметра |
QUICK_Queued_PUBLISH3(name,arg1,arg2,arg3) | асинхронный режим публикации, 3 параметра |
QUICK_BlockingQueued_PUBLISH1(name,arg1) | асинхронный ожидающий режим публикации, 1 параметр |
QUICK_BlockingQueued_PUBLISH2(name,arg1,arg2) | асинхронный ожидающий режим публикации, 2 параметра |
QUICK_BlockingQueued_PUBLISH3(name,arg1,arg2,arg3) | асинхронный ожидающий режим публикации, 3 параметра |
- | - |
QUICK_GETSET(name,type) | интерфейс быстрого чтения и записи переменных |
QUICK_INITIAL_VAR(name,type) | быстрый интерфейс определения, чтения и записи переменных |
QUICK_GETSET_Object(name,type) | интерфейс быстрой записи и чтения указателей |
- | - |
QUICK_INSTALL() | инициализация QuickController |
QUICK_INSTALL_DETAILED() | подробная инициализация QuickController, вывод подробной информации |
QUICK_SETSTYLE(name) | инициализация таблицы стилей |
— 1. После публикации события не всегда удаётся точно определить, какая функция обработки события будет вызвана. Проблема заключается в том, что система метаобъектов QT слишком сильно отличается от метода typeid() в C++. В настоящее время рекомендуется не перегружать функции обработки событий с одинаковым количеством параметров. Например:
void event_show_time(const QDateTime &time, QList<int> list);
void event_show_time(const QDateTime &time, QList<QString> list);
#true компилирует динамическую библиотеку; false компилирует статическую библиотеку;
set(quickevent_BUILD_SHARED_LIBS false)
#ON компилирует примеры OFF не компилирует примеры
set(quickevent_BUILD_EXAMPLES ON)
static int qt_metatype_id()
{
static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
if (const int id = metatype_id.loadAcquire())
return id;
//После наследования от экспортируемого класса объектов T шаблонного типа невозможно определить, требуется предварительное объявление Q_DECLARE_METATYPE
const char * const cName = T::staticMetaObject.className();
...
}
----------------- Инициализация QuickController:-----------------
Имя библиотеки: «QuickEvent»
Версия библиотеки: «3.0.1»
Контроллер QuickWorks: («High0», «High1», «High2», «Disorder2», «Disorder1», «Disorder0», «Low0», «Low1», «Low2»)
----------------------------------
«High0 Инициализация завершена»
«High1 Инициализация завершена»
«High2 Инициализация завершена»
«Disorder2 Инициализация завершена»
«Disorder1 Инициализация завершена»
«Disorder0 Инициализация завершена»
«Low0 Инициализация завершена»
«Low1 Инициализация завершена»
«Low2 Инициализация завершена»
«High0 Завершение деконструкции»
«High1 Завершение деконструкции»
«High2 Завершение деконструкции»
«Disorder2 Завершение деконструкции»
«Disorder1 Завершение деконструкции»
«Disorder0 Завершение деконструкции»
«Low0 Завершение деконструкции»
«Low1 Завершение деконструкции»
«Low2 Завершение деконструкции»
QThread(0x1b9428d5fa0, name = "Main Thread") Disorder2 Initialization QThread(0x1b9428d5fa0, name = "Main Thread") Disorder0 Initialization QThread(0x1b9428d5fa0, name = "Main Thread") Disorder1 Initialization QThread(0x1b9428d5fa0, name = "Main Thread")
Disorder0 Run QThread(0x1b9428d5fa0, name = "Main Thread") Disorder2 Run QThread(0x1b9428f94c0) Disorder3 Run msleep Begin QThread(0x1b9428f9400, name = "Work Thread") Disorder3 Run msleep End QThread(0x1b9428f9400, name = "Work Thread")
Disorder1 Run msleep Begin QThread(0x1b9428f9400, name = "Work Thread") Disorder1 Run msleep End QThread(0x1b9428f9400, name = "Work Thread") -------------quit------------- "Disorder2 End of deconstruction" "Disorder3 End of deconstruction" "Disorder1 End of deconstruction" "Disorder0 End of deconstruction"
* Примечание: 1. WorkThread — поток, который похож на MainThread, блокирует выполнение всех операций в WorkThread.
### Example4: публикация и подписка между потоками
Операция запуска потока в WorkThread будет блокировать все операции подписки в потоке WorkThread.
```cpp
----------------- QuickController Initialization:-----------------
Lib Name: "QuickEvent"
Lib VER: "3.0.1"
Controlle QuickWorks: ("MainThreadSubscibe", "MainThreadPublish", "NewThreadPublish", "WorkThreadPublish", "NewThreadSubscibe", "WorkThreadSubscibe")
----------------------------------
-------------Main Thread Publish-------------
----------------- publishEvent:-----------------
Event name: "Example4"
Event ConnectionType: Qt::AutoConnection
Event Args: Qt::AutoConnection
Event Thread: QThread(0x20815dc6640, name = "Main Thread")
----------------------------------
MainThreadSubscibe QThread(0x20815dc6640, name = "Main Thread")
NewThreadSubscibe QThread(0x20815df18b0)
-------------Work Thread Publish-------------
----------------- publishEvent:-----------------
Event name: "Example4"
Event ConnectionType: Qt::AutoConnection
Event Args: Qt::AutoConnection
Event Thread: QThread(0x20815de8820, name = "Work Thread")
----------------------------------
WorkThreadSubscibe QThread(0x20815de8820, name = "Work Thread")
MainThreadSubscibe QThread(0x20815dc6640, name = "Main Thread")
NewThreadSubscibe QThread(0x20815df18b0)
WorkThreadSubscibe QThread(0x20815de8820, name = "Work Thread")
-------------New Thread Publish-------------
----------------- publishEvent:-----------------
Event name: "Example4"
Event ConnectionType: Qt::AutoConnection
Event Args: Qt::AutoConnection
Event Thread: QThread(0x20815de86c0)
----------------------------------
MainThreadSubscibe QThread(0x20815dc6640, name = "Main Thread")
NewThreadSubscibe QThread(0x20815df18b0)
WorkThreadSubscibe QThread(0x20815de8820, name = "Work Thread")
-------------Quit-------------
----------------- QuickController Initialization:-----------------
Lib Name: "QuickEvent"
Lib VER: "3.0.1"
Controlle QuickWorks: ("NewThreadSubscibe1", "NewThreadSubscibe2")
----------------------------------
----------------- subscibeEvent:-----------------
listener: NewThreadSubscibe1(0x23c34998610)
Event name: "Example5"
subscibe level Disorder
Event Thread "Main Thread"
----------------------------------
----------------- subscibeEvent:-----------------
listener: NewThreadSubscibe2(0x23c34998950)
Event name: "Example5"
subscibe level Disorder
Event Thread "Main Thread"
----------------------------------
-------------Direct PUBLISH-------------
----------------- publishEvent:-----------------
Event name: "Example5"
Event ConnectionType: Qt::DirectConnection
Event Args: Qt::DirectConnection
Event Thread: QThread(0x23c34976690, name = "Main Thread")
----------------------------------
New1 Subscibe bugin QThread(0x23c34998570)
New2 Subscibe bugin QThread(0x23c349988d0)
New2 Subscibe end QThread(0x23c349988d0)
New1 Subscibe end QThread(0x23c34998570)
-------------Queued PUBLISH-------------
----------------- publishEvent:-----------------
Event name: "Example5"
Event ConnectionType: Qt::QueuedConnection
Event Args: Qt::QueuedConnection
Event Thread: QThread(0x23c34976690, name = "Main Thread") **New1 Subscibe bugin QThread(0x23c34998570)**
**New2 Subscibe bugin QThread(0x23c349988d0)**
**New2 Subscibe end QThread(0x23c349988d0)**
**New1 Subscibe end QThread(0x23c34998570)**
-------------Blocking Queued PUBLISH-------------
----------------- publishEvent:-----------------
Event name: «Example5»
Event ConnectionType: Qt::BlockingQueuedConnection
Event Args: Qt::BlockingQueuedConnection
Event Thread: QThread(0x23c34976690, name = «Main Thread»)
----------------------------------
**New1 Subscibe bugin QThread(0x23c34998570)**
**New1 Subscibe end QThread(0x23c34998570)**
**New2 Subscibe bugin QThread(0x23c349988d0)**
**New2 Subscibe end QThread(0x23c349988d0)**
-------------Auto PUBLISH1-------------
----------------- publishEvent:-----------------
Event name: «Example5»
Event ConnectionType: Qt::AutoConnection
Event Args: Qt::AutoConnection
Event Thread: QThread(0x23c34976690, name = «Main Thread»)
----------------------------------
**New1 Subscibe bugin QThread(0x23c34998570)**
**New2 Subscibe bugin QThread(0x23c349988d0)**
**New2 Subscibe end QThread(0x23c349988d0)**
**New1 Subscibe end QThread(0x23c34998570)**
-------------Quit-------------
«NewThreadSubscibe1 End of deconstruction»
«NewThreadSubscribe2 End of deconstruction»
*注: 1. 小心死锁,尤其跨线程阻塞同步、带QDialog等有返回值的窗口请勿使用阻塞发布*
### 。。。。持续增加中
# 6 QuickEvnet代码模型使用心得
 
 
 
 
# 7 关于作者
 **Bruce**
Gitee
https://gitee.com/fmldd
个人博客
https://me.csdn.net/dadabruce
 **Beyond欣**
Gitee
https://gitee.com/yaoxin001
个人博客
http://118.25.63.144
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )