1.送信イベントは、次の2つの機能によって完了します。
static void QCoreApplication::postEvent (QObject* receiver, QEvent* event,
int priority=Qt::NormalEventPriority);
static bool QCoreApplication::sendEvent(QObject* receiver, QEvent* event)
受信者:イベント
イベントを受信するオブジェクトを指し
ます:送信する必要のあるイベントを示します優先度:イベントの優先度を示し、イベントは優先度で並べ替えられ、優先度の高いイベントはの先頭にランク付けされますキュー。その値は、列挙型Qt :: EventPriorityの列挙値です。
次の
Qt :: HighEventPriority:値は1です。
Qt :: NormalEventPriority:値は0です。
Qt :: LowEventPriority:値は-1です。
優先度は単なる相対値であり、その値は指定された最大値と最小値の間の任意の値を取ることができます。たとえば、priorityパラメーターはQt :: HighEventPriority + 10に設定できます。
2.イベントの送信(sendEvent)とイベントの投稿(postEvent)
①イベントの送信:イベントを受信するターゲットオブジェクトにイベントを直接送信します。イベントが送信された後、それは削除されません。
送信されたイベントは通常、スタック上に作成されます。
②イベント後:
イベントをイベントキューに追加し、すぐに戻ります。
イベントを公開するには、ヒープ上にイベントを作成する必要があります(たとえば、newを使用)。イベントが公開された後、イベントキューがイベントの
所有権を取得し、自動的に削除するためです。投稿後にイベントにアクセスすることは安全ではありません。
イベントの公開では、イベントをマージすることもできます(または圧縮と呼ばれます)。たとえば、イベントループに戻る前に
複数の同一のイベントが連続して公開される場合、これらの複数の同一のイベントは自動的に1つのイベントにマージされます。マージできる
イベントには、マウス移動イベント、サイズ変更イベントなどがあります。
3.カスタムイベントの原則
①基本原則:イベントは実際には整数値で表されるため、カスタムイベントを作成する場合は、イベントの整数値を指定するだけで済みます。Qtでは、この整数値は列挙型QEvent ::で定義されます。タイプ、イベントに関するその他の情報は、カスタムクラスにカプセル化できます。
②カスタムイベントは、事前定義されたタイプまたはカスタムタイプのいずれかです。
③。カスタムタイプのイベントの場合、イベント番号を定義する必要があります。これは、QEvent :: User(値は1000)より大きく、QEvent :: MaxUser(値は65535)より小さい必要があります。
④。さまざまなイベントをオーバーラップさせることはできません(つまり、QEvent :: Typeの値を同じにすることはできません)。QEvent:: Userより小さいイベントは、Qtによって内部的に定義されたイベントであり、オーバーラップしません。カスタムイベントの場合は、 registerEventType()関数イベントがオーバーラップしないようにするために
、関数プロトタイプは次のとおりです
。staticint QEvent :: registerEventType(int Hint = -1);
ヒントの値がオーバーラップしない場合、この値が返されます。 ;ヒントが無効な場合、システムは自動的に1つの
Aの有効な値を割り当てて返します。したがって、この関数の戻り値を使用して、Type型の値を作成できます。
4.カスタムイベントを作成する方法と手順
①。次のメソッドを使用してカスタムイベントを作成できます
。QEventのコンストラクターを使用してイベントを作成します。プロトタイプは次の
とおりです。QEvent(Type type);
例:QEvent :: Type t1 =(QEvent :: Type)1333; //定義イベント番号
QEvente(t); //イベントの作成e
は、QKeyEventクラスを使用してキーボードイベントを作成するなど、Qtが作成したイベントタイプを使用してイベントを作成します。
QEventクラスを継承し、カスタムイベントを作成します。
②QCoreApplication:: postEvent()またはQCoreApplication :: sendEvent()関数を使用してイベントを送信します。
③。以下のメソッドを使用してカスタムイベントを処理できます
。QObject:: event()関数を書き直し、この関数でカスタムイベントを直接処理するか、カスタムイベント
ハンドラーを呼び出してイベントを処理します。
イベントフィルターをインストールしてから、フィルターオブジェクトのeventFilter()関数でカスタムイベントを処理します。
もちろん、QCoreApplication :: notify()関数を書き直すこともできます。
カスタムイベントのデモ:
#include <QApplication>
#include<QWidget>
#include<QObject>
#include <iostream>
using namespace std;
QEvent::Type t1=(QEvent::Type)1333;
QEvent e(t1); //使用 QEvent 的构造函数在堆栈上创建自定义事件
class E:public QEvent{
public: //子类化 QEvent 以创建自定义事件
//方式 1:使用静态成员。
//使用静态成员主要是为了正确初始化父类部分 QEvent,比如
//E():t2((QEvent::Type)1324),QEvent(t2){}, 若 t2 不是静态的,则则初始化之后 t2 为 1324,但传递
//给 QEvent 的 t2 是一个不确定的值,因为按照 C++规则,对父类部分的初始化先于数据成员的初始化。
static QEvent::Type t2; //注意:不要使用名称 t,因为 QEvent 类之中有一个名称为 t 的成员变量。
E():QEvent(t2){}
//方式 2:使用带一个参数的构造函数
QEvent::Type t3;
explicit E(QEvent::Type t4):t3(t4),QEvent(t4){}
};
QEvent::Type E::t2=(QEvent::Type)1334;
class A:public QWidget{
public:
bool event(QEvent* e)
{ //重写 event 函数以处理自定义事件
if(e->type()==t1) //判断事件类型是否为 t1
{
cout<<"AE"<<e->type()<<",";
f1((E*)e); //调用自定义的处理函数处理该事件
return 1;
}
if(e->type()==E::t2)
{
cout<<"BE"<<e->type()<<",";
f2((QEvent*)e); return 1;
}
if(e->type()==((E*)e)->t3)
{
cout<<"CE"<<e->type()<<",";
f3((E*)e); return 1;
}
return QWidget::event(e);
} //event 结束
//以下为处理自定义事件的事件处理函数
void f1(E *e)
{
cout<<"F1"<<endl;
}
void f2(QEvent *e)
{
cout<<"F2"<<endl;
}
void f3(E *e)
{
cout<<"F3"<<endl;
}
}; //类 A 结束。
int main(int argc, char *argv[])
{
QApplication aa(argc,argv);
A ma;
E me;
E *pe=new E((QEvent::Type)1335);
//发布或发送事件
aa.sendEvent(&ma,&e);
aa.sendEvent(&ma,&me);
aa.postEvent(&ma,pe);
//aa.postEvent(&ma,&me); //错误,发布的事件 me 必须是在堆上创建的。
ma.resize(333,222);
ma.show();
aa.exec();
return 0;
}
イベントフィルターを使用して、カスタムイベントデモを処理します。
#include <QApplication>
#include<QWidget>
#include<QObject>
#include <iostream>
using namespace std;
QEvent::Type t1=(QEvent::Type)QEvent::registerEventType(1333);
QEvent e1(t1); //使用 QEvent 的构造函数创建自定义事件
//t2 的值与 t1 重复,使用 registerEventType 会自动产生一个合法的值
QEvent::Type t2=(QEvent::Type)QEvent::registerEventType(1333);
QEvent e2(t2);
class A:public QWidget{
public:
bool event(QEvent* e)
{
if(e->type()==t1)
{
cout<<"AE"<<e->type()<<",";
f1((QEvent*)e);
return 1;
}
if(e->type()==t2)
{
cout<<"BE"<<e->type()<<",";
f2((QEvent*)e);
return 1;
}
return QWidget::event(e);
} //event 结束
void f1(QEvent *e)
{
cout<<"F1"<<endl;
}
void f2(QEvent *e)
{
cout<<"F2"<<endl;
}
};
class B:public QObject{public:
bool eventFilter(QObject *w, QEvent *e)
{
if(e->type()==t1)
{
cout<<"A"<<endl;return 1;
}
if(e->type()==t2)
{
cout<<"B"<<endl;return 0;
}
return 0;
}
};
int main(int argc, char *argv[])
{
QApplication aa(argc,argv);
A ma;
B mb;
ma.installEventFilter(&mb); //安装事件过滤器
aa.sendEvent(&ma,&e1);
aa.sendEvent(&ma,&e2);
ma.resize(333,222);
ma.show();
aa.exec();
return 0;
}
この例では、AB BE65535、F2を順番に出力します。ここで、65535は、registerEventType関数を使用してt2に割り当てられた有効な値です。イベントフィルターがインストールされた後、送信されたイベントe1とe2は、フィルターオブジェクトのeventFilter関数を使用して処理されることがわかります。
5.イベントの配信シーケンスの要約
event()関数、イベントフィルター、およびイベント処理関数の呼び出しシーケンスは次のとおりです。
最初にイベントフィルターを逆の順序で呼び出し(同じオブジェクトに複数のイベントフィルターがインストールされている)、次にevent()関数を呼び出し、最後にを呼び出します。イベント処理関数(注:イベント処理関数は、event()関数で明示的または間接的に呼び出す必要があります。そうしないと、イベント処理関数は呼び出されません)。