>> الصفحة الرئيسية >> مقالات ZetCode >> [6] الأحداث و الإشارات في Qt4

الأقسام الرئيسية

 التنصيب والاعداد التنصيب والاعداد
 دروس متقدمة دروس متقدمة
 سلسلة دروس للمبتدئين سلسلة دروس للمبتدئين
 اساسيات لغة سي++ اساسيات لغة سي++
 مقالات ZetCode مقالات ZetCode
 

جديد الدروس

 الوحدة QtUiTools (واجهة المستخدم ديناميكية التوليد)
التاريخ 04/07/2009 الوحدة QtUiTools (واجهة المستخدم ديناميكية التوليد)
 Qt and Phonon
التاريخ 04/07/2009 Qt and Phonon
 تتمة الرسائل ومربعات الحوار في qt
التاريخ 04/07/2009 تتمة الرسائل ومربعات الحوار في qt
 مدخل الى xml في Qt
التاريخ 04/07/2009 مدخل الى xml في Qt
 الإدخال والإخراج لبيانات الفئات
التاريخ 04/07/2009 الإدخال والإخراج لبيانات الفئات
 

[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

  1. #ifndef CLICK_H
  2. #define CLICK_H
  3.  
  4. #include <QWidget>
  5.  
  6. class Click : public QWidget
  7. {
  8. public:
  9. Click(QWidget *parent = 0);
  10.  
  11. };
  12.  
  13. #endif
  14. Header file.
  15. lines.cpp
  16.  
  17. #include "click.h"
  18. #include <QPushButton>
  19. #include <QApplication>
  20.  
  21.  
  22. Click::Click(QWidget *parent)
  23. : QWidget(parent)
  24. {
  25. QPushButton *quit = new QPushButton("Quit", this);
  26. quit->setGeometry(50, 40, 75, 30);
  27.  
  28. connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
  29. }

قمنا بإضهار QPushButton على النافذة .
الدالة connect() تقوم بإيصال الإشارات الى المستقبلات ,اثناء النقر على زر إغلاق البرنامج يتم توليد إشارة النقر clicked() . qApp هي مؤشر عام لكائن التطبيق . وهي معرفة في ملف الرأس QApllication.h أما الدالة quit فيتم استدعائها بالتزامن مع ارسال إشارة clicked .
main.cpp

  1. #include "click.h"
  2. #include <QDesktopWidget>
  3. #include <QApplication>
  4.  
  5. void center(QWidget &widget)
  6. {
  7. int x, y;
  8. int screenWidth;
  9. int screenHeight;
  10.  
  11. int WIDTH = 250;
  12. int HEIGHT = 150;
  13.  
  14.  
  15. QDesktopWidget *desktop = QApplication::desktop();
  16.  
  17. screenWidth = desktop->width();
  18. screenHeight = desktop->height();
  19.  
  20. x = (screenWidth - WIDTH) / 2;
  21. y = (screenHeight - HEIGHT) / 2;
  22.  
  23. widget.setGeometry(x, y, WIDTH, HEIGHT);
  24. widget.setFixedSize(WIDTH, HEIGHT);
  25. }
  26.  
  27.  
  28. int main(int argc, char *argv[])
  29. {
  30. QApplication app(argc, argv);
  31.  
  32. Click window;
  33.  
  34. window.setWindowTitle("Click");
  35. window.show();
  36. center(window);
  37.  
  38. return app.exec();
  39. }

Main file.


Figure: النقر
ضغط المفاتيح:-
في هذا المثال سوف نقوم بعمل تطبيق يتفاعل مع ضغط المفاتيح
keypress.h

  1. #ifndef KEYPRESS_H
  2. #define KEYPRESS_H
  3.  
  4. #include <QWidget>
  5.  
  6. class KeyPress : public QWidget
  7. {
  8. public:
  9. KeyPress(QWidget *parent = 0);
  10.  
  11. protected:
  12. void keyPressEvent(QKeyEvent * event);
  13.  
  14. };
  15.  
  16. #endif
  17. Header file.
  18. keypress.cpp
  19.  
  20. #include "keypress.h"
  21.  
  22. #include <QApplication>
  23. #include <QKeyEvent>
  24.  
  25. KeyPress::KeyPress(QWidget *parent)
  26. : QWidget(parent)
  27. {
  28.  
  29. }
  30.  
  31. void KeyPress::keyPressEvent(QKeyEvent *event)
  32. {
  33. if (event->key() == Qt::Key_Escape) {
  34. qApp->quit();
  35. }
  36. }


يتم الخروج من التطبيق عند الضغط على المفتاح Escape .
  1. void KeyPress::keyPressEvent(QKeyEvent *event)
  2. {
  3. if (event->key() == Qt::Key_Escape) {
  4. qApp->quit();
  5. }
  6. }

أحد الطرق في التعامل مع الأحداث في مكتبة Qt تكون بإستخدام معالج الحدث . والفئة QKeyEvent هو كائن يقوم بحمل معلومات عن ما حدث في لوحة المفاتيح . في حالتنا نحن نستخدم كائن حدث يحدد الزر الذي تم ضغطه .
main.cpp

  1. #include "keypress.h"
  2. #include <QDesktopWidget>
  3. #include <QApplication>
  4.  
  5. void center(QWidget &widget)
  6. {
  7. int x, y;
  8. int screenWidth;
  9. int screenHeight;
  10.  
  11. int WIDTH = 250;
  12. int HEIGHT = 150;
  13.  
  14. QDesktopWidget *desktop = QApplication::desktop();
  15.  
  16. screenWidth = desktop->width();
  17. screenHeight = desktop->height();
  18.  
  19. x = (screenWidth - WIDTH) / 2;
  20. y = (screenHeight - HEIGHT) / 2;
  21.  
  22. widget.setGeometry(x, y, WIDTH, HEIGHT);
  23. widget.setFixedSize(WIDTH, HEIGHT);
  24. }
  25.  
  26.  
  27. int main(int argc, char *argv[])
  28. {
  29. QApplication app(argc, argv);
  30.  
  31. KeyPress window;
  32.  
  33. window.setWindowTitle("Key press");
  34. window.show();
  35. center(window);
  36.  
  37. return app.exec();
  38. }

Main file.
QMoveEvent
وهي فئة تحوي وسائط لحمل معلومات أحداث الحركة . حدث الحركة ترسل الى النافذة عندما يتم تحريك النافذة .
move.h

  1. #ifndef MOVE_H
  2. #define MOVE_H
  3.  
  4. #include <QMainWindow&Gt;
  5.  
  6. class Move : public QWidget
  7. {
  8.  
  9. public:
  10. Move(QWidget *parent = 0);
  11.  
  12. protected:
  13. void moveEvent(QMoveEvent *event);
  14.  
  15. };
  16.  
  17. #endif
  18. Header file.
  19. move.cpp
  20.  
  21. #include "move.h"
  22. #include <QMoveEvent>
  23.  
  24. Move::Move(QWidget *parent)
  25. : QWidget(parent)
  26. {
  27.  
  28. }
  29.  
  30. void Move::moveEvent(QMoveEvent *event)
  31. {
  32. int x = event->pos().x();
  33. int y = event->pos().y();
  34.  
  35. QString text = QString::number(x) + "," + QString::number(y);
  36.  
  37. setWindowTitle(text);
  38. }

هذا المثال يتفاعل مع حدث الحركة حيث قمنا بتحديد الإحداثيين x و y للزاوية اليسرى العليا في النافذة وثم قمنا بوضع الناتج مكان عنوان النافذة .
  1. int x = event->pos().x();
  2. int y = event->pos().y();
  3. أستخدمنا الكائن QMoveEvent لتحديد قيمتي x و y .
  4. QString text = QString::number(x) + "," + QString::number(y);
قمنا بتحويل الأرقام الى نص.
  1. setWindowTitle(text);

ثم وضعنا النص في مكان عنوان النافذة .
main.cpp

  1. #include "move.h"
  2. #include <QDesktopWidget>
  3. #include <QApplication>
  4.  
  5. void center(QWidget &widget)
  6. {
  7. int x, y;
  8. int screenWidth;
  9. int screenHeight;
  10.  
  11. int WIDTH = 250;
  12. int HEIGHT = 150;
  13.  
  14. QDesktopWidget *desktop = QApplication::desktop();
  15.  
  16. screenWidth = desktop->width();
  17. screenHeight = desktop->height();
  18.  
  19. x = (screenWidth - WIDTH) / 2;
  20. y = (screenHeight - HEIGHT) / 2;
  21.  
  22. widget.setGeometry(x, y, WIDTH, HEIGHT);
  23. widget.setFixedSize(WIDTH, HEIGHT);
  24. }
  25.  
  26.  
  27. int main(int argc, char *argv[])
  28. {
  29. QApplication app(argc, argv);
  30.  
  31. Move window;
  32.  
  33. window.setWindowTitle("Move");
  34. window.show();
  35. center(window);
  36.  
  37. return app.exec();
  38. }

Main file.


Figure: QMoveEvent
قطع الإتصال
يمكنك قطع االإتصال بين الإشارات والمستقبلات ,في المثال التالي سوف نرى كيف يمكننا أن نقوم بفعل ذلك .
disconnect.h

  1. #ifndef DISCONNECT_H
  2. #define DISCONNECT_H
  3.  
  4. #include <QWidget>
  5. #include <QPushButton>
  6.  
  7. class Disconnect : public QWidget
  8. {
  9. Q_OBJECT
  10.  
  11. public:
  12. Disconnect(QWidget *parent = 0);
  13.  
  14. private slots:
  15. void onClick();
  16. void onCheck(int);
  17.  
  18. private:
  19. QPushButton *click;
  20.  
  21. };
  22.  
  23. #endif

في ملف الرأس قمنا بالتصريح عن مستقبلين . slots ليست كلمة مفتاحية في c++ بل هي ضمن امتداد مكتبة Qt هذا الإمتداد يتم معالجته قبل ترجمة الشيفرة عند إستخدام signals و slots في فئتنا يجب وضع الماكرو Q_OBJECT في بداية تعريفنا للفئة . فيما عدا ذلك سوف يتم ارسال خطأ ماقبل المعالجة .
disconnect.cpp

  1. #include "disconnect.h"
  2. #include <QTextStream>
  3. #include <QCheckBox>
  4.  
  5.  
  6. Disconnect::Disconnect(QWidget *parent)
  7. : QWidget(parent)
  8. {
  9. click = new QPushButton("Click", this);
  10. click->setGeometry(50, 40, 75, 30);
  11.  
  12. QCheckBox *cb = new QCheckBox("Connect", this);
  13. cb->setCheckState(Qt::Checked);
  14. cb->move(150, 40);
  15.  
  16. connect(click, SIGNAL(clicked()),
  17. this, SLOT(onClick()));
  18. connect(cb, SIGNAL(stateChanged(int)),
  19. this, SLOT(onCheck(int)));
  20. }
  21.  
  22. void Disconnect::onClick()
  23. {
  24. QTextStream out(stdout);
  25. out << "Button clickedn";
  26. }
  27.  
  28. void Disconnect::onCheck(int state)
  29. {
  30. if (state == Qt::Checked) {
  31. connect(click, SIGNAL(clicked()),
  32. this, SLOT(onClick()));
  33. } else {
  34. click->disconnect(SIGNAL(clicked()));
  35. }
  36. }

في مثالنا لدينا زر ومربع تأكيد. مربع التأكيد يقوم بالإتصال وقطع الإتصال بين المستقبل و إشارة نقرة الزر .يجب تنفيذ هذا المثال من خلال سطر الأوامر .
  1. connect(click, SIGNAL(clicked()),
  2. this, SLOT(onClick()));
  3. connect(cb, SIGNAL(stateChanged(int)),
  4. this, SLOT(onCheck(int)));

هنا قمنا ب ربط الإشارات ب المستقبل الذي قمنا بتعريفه
  1. void Disconnect::onClick()
  2. {
  3. QTextStream out(stdout);
  4. out << "Button clickedn";
  5. }

اذا قمنا بالنقر على الز سوف نرسل النص "button text" الى النافذة الطرفية .
  1. void Disconnect::onCheck(int state)
  2. {
  3. if (state == Qt::Checked) {
  4. connect(click, SIGNAL(clicked()),
  5. this, SLOT(onClick()));
  6. } else {
  7. click->disconnect(SIGNAL(clicked()));
  8. }
  9. }

في داخل المستقبل onCheck() ربطنا/قطعنا الإتصال بين إشارة النقر والمستقبل onClick() .
main.cpp

  1. #include "disconnect.h"
  2. #include <QDesktopWidget>
  3. #include <QApplication>
  4.  
  5. void center(QWidget &widget)
  6. {
  7. int x, y;
  8. int screenWidth;
  9. int screenHeight;
  10.  
  11. int WIDTH = 250;
  12. int HEIGHT = 150;
  13.  
  14. QDesktopWidget *desktop = QApplication::desktop();
  15.  
  16. screenWidth = desktop->width();
  17. screenHeight = desktop->height();
  18.  
  19. x = (screenWidth - WIDTH) / 2;
  20. y = (screenHeight - HEIGHT) / 2;
  21.  
  22. widget.setGeometry(x, y, WIDTH, HEIGHT);
  23. widget.setFixedSize(WIDTH, HEIGHT);
  24. }
  25.  
  26. int main(int argc, char *argv[])
  27. {
  28. QApplication app(argc, argv);
  29.  
  30. Disconnect window;
  31.  
  32. window.setWindowTitle("Disconnect");
  33. window.show();
  34. center(window);
  35.  
  36. return app.exec();
  37. }
  38. Main file.



Figure: قطع الإتصال
المؤقت
وتستخدم في ارسال إشارة او امهام التي تتكرر بشكل مؤقت ومثال جيد على هذا هو الساعة حيث يجب أن نقوم في كل ثانية تغيير التوقيت الى التوقيت الحالي .
timer.h

  1. #ifndef TIMER_H
  2. #define TIMER_H
  3.  
  4. #include <QWidget>
  5. #include <QLabel>
  6.  
  7. class Timer : public QWidget
  8. {
  9. public:
  10. Timer(QWidget *parent = 0);
  11.  
  12. protected:
  13. void timerEvent(QTimerEvent *event);
  14.  
  15. private:
  16. QLabel *label;
  17.  
  18. };
  19.  
  20. #endif
  21. Header file.
  22. timer.cpp
  23.  
  24. #include "timer.h"
  25.  
  26. #include <QTime>
  27.  
  28.  
  29. Timer::Timer(QWidget *parent)
  30. : QWidget(parent)
  31. {
  32.  
  33. label = new QLabel("", this);
  34. label->move(50, 50);
  35.  
  36. QTime qtime = QTime::currentTime();
  37. QString stime = qtime.toString(Qt::LocalDate);
  38. label->setText(stime);
  39.  
  40. startTimer(1000);
  41. }
  42.  
  43. void Timer::timerEvent(QTimerEvent *event)
  44. {
  45. QTime qtime = QTime::currentTime();
  46. QString stime = qtime.toString(Qt::LocalDate);
  47. label->setText(stime);
  48. }

في هذا المثال قمنا بإستعراض الوقت على النافذة .
  1. label = new QLabel("", this);
  2. label->move(50, 50);
لعرض التوقيت أتخدمنا النافذة label.
  1. QTime qtime = QTime::currentTime();
  2. QString stime = qtime.toString(Qt::LocalDate);
  3. label->setText(stime);

هنا قمنا بتحديد الوقت الحالي ووضعه في النافذة label .
startTimer(1000);
بداية المئقت كل 1000 ملي ثانية يتم توليد حدث المؤقت
  1. void Timer::timerEvent(QTimerEvent *event)
  2. {
  3. QTime qtime = QTime::currentTime();
  4. QString stime = qtime.toString(Qt::LocalDate);
  5. label->setText(stime);
  6. }

لتعمل مع أحداث المؤقت يجب إعادة تعريف الدالة timerEvent() .
main.cpp

  1. #include "timer.h"
  2. #include <QDesktopWidget>
  3. #include <QApplication>
  4.  
  5. void center(QWidget &widget)
  6. {
  7. int x, y;
  8. int screenWidth;
  9. int screenHeight;
  10.  
  11. int WIDTH = 250;
  12. int HEIGHT = 150;
  13.  
  14. QDesktopWidget *desktop = QApplication::desktop();
  15.  
  16. screenWidth = desktop->width();
  17. screenHeight = desktop->height();
  18.  
  19. x = (screenWidth - WIDTH) / 2;
  20. y = (screenHeight - HEIGHT) / 2;
  21.  
  22. widget.setGeometry(x, y, WIDTH, HEIGHT);
  23. widget.setFixedSize(WIDTH, HEIGHT);
  24. }
  25.  
  26.  
  27. int main(int argc, char *argv[])
  28. {
  29. QApplication app(argc, argv);
  30.  
  31. Timer window;
  32.  
  33. window.setWindowTitle("Timer");
  34. window.show();
  35. center(window);
  36.  
  37. return app.exec();
  38. }

Main file.


Figure: المؤقت

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

الأكثر زيارة

 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير QDevelop
الزيارات 2320 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير QDevelop
 اعداد وتنصيب Qt
الزيارات 2161 اعداد وتنصيب Qt
 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
الزيارات 2128 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
 C++ In a Nutshell
الزيارات 1904 C++ In a Nutshell
 التطوير السريع للتطبيقات Rapid Application Development
الزيارات 1862 التطوير السريع للتطبيقات Rapid Application Development
 

الأكثر تصويتـا

 اعداد وتنصيب Qt
نتيجة التصويت 40 من 5 شخص اعداد وتنصيب Qt
 تخطيط البرامج Program Layout
نتيجة التصويت 40 من 6 شخص تخطيط البرامج Program Layout
 التطوير السريع للتطبيقات Rapid Application Development
نتيجة التصويت 29 من 4 شخص التطوير السريع للتطبيقات Rapid Application Development
 الدرس الثالث:تعريف slot جديدة
نتيجة التصويت 27 من 3 شخص الدرس الثالث:تعريف slot جديدة
 دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
نتيجة التصويت 22 من 3 شخص دليل تنصيب اطار عمل Qt ، حزمة MinGW ، بيئة التطوير Eclipse
 
 

سكربت story-script v1 برمجة bwady.com تطوير SudaNix