|
|
|
[6] الأحداث و الإشارات في Qt4 |
|
في هذا الجزء من سلسلة دروس Qt4 c++ سوف نتحدث عن الأحداث والإشارات .
تعتبر الأحداث جزء مهم في برمجة واجهة المستخدم الرسومية . جميع تطبيقات واجهة المستخدم الرسومية هي event-driven . حيث تتفاعل التطبيقات مع أحداث مختلفة الأنواع أثناء دورة حياتها . وتنشأ الأحداث من مستخدم التطبيق وقد تنشأ بطرق أخرى مثل الإتصال بالشبكة أو مدير النوافذ أو المؤقت .
هناك ثلاثة مشاركين في نمذجة الحدث :-
1- مصدر الحدث event source.
2- كائن الحدث event object.
3- هدف الحدث event target.
مصدر الحدث هو الكائن الذي تغير حاله (ناشئ الحدث) أما كائن الحدث فهو الذي يغلف الحدث المنشأ من مصدر الحدث أم هدف الحدث فهو الكائن الذي سوف يشعر(يتم إعلامه) بحدوث الحدث حيث يقوم كائن مصدر الحدث بتفويض هدف الحدث ليقوم بمعالجة الحدث .
أثناء استدعاء الدالة exec() في الدالى main فإنه يحدث تكرار لما في داخل الدالة main وأثناء التكرار الرئيس يتم جلب الأحداث وارسالها الى الكائنات ولتسهيل التعامل مع هذه العملية قامت شركة تورليتك بإنشاء آلية slot و signal (الإرسال والإستقبال) وهذه الآلية (slot و signal) هي توسعة للبرمجة بلغة c++ .
ويمكن تعريفها بأنها آلية إتصال بين الكائنات .ويتم ارسال الإشارات في حال حدث حدث معين .ويتم تنفيذ slot في حال تم إرسال اشارة .
النقر:-
المثال الأول هو مثال لمعالجة حدث بسيط , حيث هناك زر واحد عند الضغط عليه يتم إقفال التطبيق.
lines.h
#ifndef CLICK_H #define CLICK_H #include <QWidget> { public: }; #endif Header file. lines.cpp #include "click.h" #include <QPushButton> #include <QApplication> { quit->setGeometry(50, 40, 75, 30); connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); }
|
قمنا بإضهار QPushButton على النافذة .
الدالة connect() تقوم بإيصال الإشارات الى المستقبلات ,اثناء النقر على زر إغلاق البرنامج يتم توليد إشارة النقر clicked() . qApp هي مؤشر عام لكائن التطبيق . وهي معرفة في ملف الرأس QApllication.h أما الدالة quit فيتم استدعائها بالتزامن مع ارسال إشارة clicked .
main.cpp
#include "click.h" #include <QDesktopWidget> #include <QApplication> { int x, y; int screenWidth; int screenHeight; int WIDTH = 250; int HEIGHT = 150; screenWidth = desktop->width(); screenHeight = desktop->height(); x = (screenWidth - WIDTH) / 2; y = (screenHeight - HEIGHT) / 2; widget.setGeometry(x, y, WIDTH, HEIGHT); widget.setFixedSize(WIDTH, HEIGHT); } int main(int argc, char *argv[]) { Click window; window.setWindowTitle("Click"); window.show(); center(window); return app.exec(); }
|
Main file.

Figure: النقر
ضغط المفاتيح:-
في هذا المثال سوف نقوم بعمل تطبيق يتفاعل مع ضغط المفاتيح
keypress.h
#ifndef KEYPRESS_H #define KEYPRESS_H #include <QWidget> { public: protected: }; #endif Header file. keypress.cpp #include "keypress.h" #include <QApplication> #include <QKeyEvent> KeyPress ::KeyPress(QWidget *parent ){ } void KeyPress ::keyPressEvent(QKeyEvent *event ) { if (event->key() == Qt::Key_Escape) { qApp->quit(); } }
|
يتم الخروج من التطبيق عند الضغط على المفتاح Escape .
void KeyPress ::keyPressEvent(QKeyEvent *event ) { if (event->key() == Qt::Key_Escape) { qApp->quit(); } }
|
أحد الطرق في التعامل مع الأحداث في مكتبة Qt تكون بإستخدام معالج الحدث . والفئة QKeyEvent هو كائن يقوم بحمل معلومات عن ما حدث في لوحة المفاتيح . في حالتنا نحن نستخدم كائن حدث يحدد الزر الذي تم ضغطه .
main.cpp
#include "keypress.h" #include <QDesktopWidget> #include <QApplication> { int x, y; int screenWidth; int screenHeight; int WIDTH = 250; int HEIGHT = 150; screenWidth = desktop->width(); screenHeight = desktop->height(); x = (screenWidth - WIDTH) / 2; y = (screenHeight - HEIGHT) / 2; widget.setGeometry(x, y, WIDTH, HEIGHT); widget.setFixedSize(WIDTH, HEIGHT); } int main(int argc, char *argv[]) { KeyPress window; window.setWindowTitle("Key press"); window.show(); center(window); return app.exec(); }
|
Main file.
QMoveEvent
وهي فئة تحوي وسائط لحمل معلومات أحداث الحركة . حدث الحركة ترسل الى النافذة عندما يتم تحريك النافذة .
move.h
#ifndef MOVE_H #define MOVE_H #include <QMainWindow≫ { public: protected: }; #endif Header file. move.cpp #include "move.h" #include <QMoveEvent> { } { int x = event->pos().x(); int y = event->pos().y(); setWindowTitle(text); }
|
هذا المثال يتفاعل مع حدث الحركة حيث قمنا بتحديد الإحداثيين x و y للزاوية اليسرى العليا في النافذة وثم قمنا بوضع الناتج مكان عنوان النافذة .
int x = event->pos().x(); int y = event->pos().y();
|
قمنا بتحويل الأرقام الى نص.
ثم وضعنا النص في مكان عنوان النافذة .
main.cpp
#include "move.h" #include <QDesktopWidget> #include <QApplication> { int x, y; int screenWidth; int screenHeight; int WIDTH = 250; int HEIGHT = 150; screenWidth = desktop->width(); screenHeight = desktop->height(); x = (screenWidth - WIDTH) / 2; y = (screenHeight - HEIGHT) / 2; widget.setGeometry(x, y, WIDTH, HEIGHT); widget.setFixedSize(WIDTH, HEIGHT); } int main(int argc, char *argv[]) { Move window; window.setWindowTitle("Move"); window.show(); center(window); return app.exec(); }
|
Main file.

Figure: QMoveEvent
قطع الإتصال
يمكنك قطع االإتصال بين الإشارات والمستقبلات ,في المثال التالي سوف نرى كيف يمكننا أن نقوم بفعل ذلك .
disconnect.h
#ifndef DISCONNECT_H #define DISCONNECT_H #include <QWidget> #include <QPushButton> { Q_OBJECT public: private slots: void onClick(); void onCheck(int); private: }; #endif
|
في ملف الرأس قمنا بالتصريح عن مستقبلين . slots ليست كلمة مفتاحية في c++ بل هي ضمن امتداد مكتبة Qt هذا الإمتداد يتم معالجته قبل ترجمة الشيفرة عند إستخدام signals و slots في فئتنا يجب وضع الماكرو Q_OBJECT في بداية تعريفنا للفئة . فيما عدا ذلك سوف يتم ارسال خطأ ماقبل المعالجة .
disconnect.cpp
#include "disconnect.h" #include <QTextStream> #include <QCheckBox> Disconnect ::Disconnect(QWidget *parent ){ click->setGeometry(50, 40, 75, 30); cb->setCheckState(Qt::Checked); cb->move(150, 40); connect(click, SIGNAL(clicked()), this, SLOT(onClick())); connect(cb, SIGNAL(stateChanged(int)), this, SLOT(onCheck(int))); } void Disconnect::onClick() { out << "Button clickedn"; } void Disconnect::onCheck(int state) { if (state == Qt::Checked) { connect(click, SIGNAL(clicked()), this, SLOT(onClick())); } else { click->disconnect(SIGNAL(clicked())); } }
|
في مثالنا لدينا زر ومربع تأكيد. مربع التأكيد يقوم بالإتصال وقطع الإتصال بين المستقبل و إشارة نقرة الزر .يجب تنفيذ هذا المثال من خلال سطر الأوامر .
connect(click, SIGNAL(clicked()), this, SLOT(onClick())); connect(cb, SIGNAL(stateChanged(int)), this, SLOT(onCheck(int)));
|
هنا قمنا ب ربط الإشارات ب المستقبل الذي قمنا بتعريفه
void Disconnect::onClick() { out << "Button clickedn"; }
|
اذا قمنا بالنقر على الز سوف نرسل النص "button text" الى النافذة الطرفية .
void Disconnect::onCheck(int state) { if (state == Qt::Checked) { connect(click, SIGNAL(clicked()), this, SLOT(onClick())); } else { click->disconnect(SIGNAL(clicked())); } }
|
في داخل المستقبل onCheck() ربطنا/قطعنا الإتصال بين إشارة النقر والمستقبل onClick() .
main.cpp
#include "disconnect.h" #include <QDesktopWidget> #include <QApplication> { int x, y; int screenWidth; int screenHeight; int WIDTH = 250; int HEIGHT = 150; screenWidth = desktop->width(); screenHeight = desktop->height(); x = (screenWidth - WIDTH) / 2; y = (screenHeight - HEIGHT) / 2; widget.setGeometry(x, y, WIDTH, HEIGHT); widget.setFixedSize(WIDTH, HEIGHT); } int main(int argc, char *argv[]) { Disconnect window; window.setWindowTitle("Disconnect"); window.show(); center(window); return app.exec(); } Main file.
|

Figure: قطع الإتصال
المؤقت
وتستخدم في ارسال إشارة او امهام التي تتكرر بشكل مؤقت ومثال جيد على هذا هو الساعة حيث يجب أن نقوم في كل ثانية تغيير التوقيت الى التوقيت الحالي .
timer.h
#ifndef TIMER_H #define TIMER_H #include <QWidget> #include <QLabel> { public: protected: private: }; #endif Header file. timer.cpp #include "timer.h" #include <QTime> { label->move(50, 50); QString stime = qtime. toString(Qt ::LocalDate); label->setText(stime); startTimer(1000); } { QString stime = qtime. toString(Qt ::LocalDate); label->setText(stime); }
|
في هذا المثال قمنا بإستعراض الوقت على النافذة .
لعرض التوقيت أتخدمنا النافذة label.
QString stime = qtime. toString(Qt ::LocalDate); label->setText(stime);
|
هنا قمنا بتحديد الوقت الحالي ووضعه في النافذة label .
startTimer(1000);
بداية المئقت كل 1000 ملي ثانية يتم توليد حدث المؤقت
{ QString stime = qtime. toString(Qt ::LocalDate); label->setText(stime); }
|
لتعمل مع أحداث المؤقت يجب إعادة تعريف الدالة timerEvent() .
main.cpp
#include "timer.h" #include <QDesktopWidget> #include <QApplication> { int x, y; int screenWidth; int screenHeight; int WIDTH = 250; int HEIGHT = 150; screenWidth = desktop->width(); screenHeight = desktop->height(); x = (screenWidth - WIDTH) / 2; y = (screenHeight - HEIGHT) / 2; widget.setGeometry(x, y, WIDTH, HEIGHT); widget.setFixedSize(WIDTH, HEIGHT); } int main(int argc, char *argv[]) { Timer window; window.setWindowTitle("Timer"); window.show(); center(window); return app.exec(); }
|
Main file.

Figure: المؤقت
| إسم الكاتب |
تاريخ الإضافة |
التقييم / المقيمين |
زيارات الدرس |
| مصفوفة |
09/01/2009 |
10 / 1 |
558 |
|
|
|
|