[10] تصميم أداة نافذة widget بمواصفات خاصة في Qt4



تصميم أداة نافذة widget بمواصفات خاصة في Qt4


في هذا الجزء من سلسلة درورس Qt4, سنقوم بعمل أداة widget بمواصفات خاصة بحسب رغبتنا نحن.

هل مرةً نظرت إلى تطبيق ما و تعجبت و تساءلت, كيف تم إنشاء و عمل عنصر أو اداة معينة؟ من المحتمل أن كل مبرمج في البداية تسائل و تعجب من ذلك. و من ثم هل كنت تنظر إلى قائمة أدوات مُقدمة من المكتبة الرسومية المفضلة لديك. و لكنك لم تستطع أن تجدها.

حقيبة الأدوات البرمجية Toolkits عادةً تُقدم فقط الأدوات الشائعة الإستعمال مثل الزرارات Buttons و الأدوات النصيّة text widgets, و المزلاج sliders...الخ. و ليست هناك أي حقيبة ادوات برمجية Toolkit تحتوي على كل الأدوات الممكنة.

البرمجون يجب عليهم إنشاء و عمل مثل هذه الأدوات بأنفسهم. يقومون بذلك بواسطة استعمال أدوات للرسم منخفضة المستوى مزودة و مُقدمة بواسطة حقيبة الأدوات الرئيسية للمكتبة. هناك إمكانيتان لعمل ذلك و هي:

- المبرمج يستطيع تعديل او تحسين أداة widget موجودة مسبقاً.
- المبرمج يستطيع خلق و إنشاء أداة widget بمواصفات خاصة من الصفر(من البداية).


أداة لقياس عملية الحرق البياني للأقراص The Burning widget:

في المثال التالي سنقوم بإنشاء أداة رسومية مرئية تحاكي عملية تخزين\حرق بياني للأقراص. هذه الأداة يمكن مشاهدتها في تطبيقات برمجية مثل Nero أو K3B. الأداة ستكون معمولة من الصفر (من البداية).

[left]burning.h[/left]
  1. #ifndef BURNING_H
  2. #define BURNING_H
  3.  
  4. #include <QWidget>
  5. #include <QSlider>
  6. #include 'widget.h'
  7.  
  8.  
  9. class Burning : public QFrame
  10. {
  11. Q_OBJECT
  12.  
  13. public:
  14. Burning(QWidget *parent = 0);
  15.  
  16. public slots:
  17. void valueChanged(int);
  18. int getCurrentWidth();
  19.  
  20. private:
  21. QSlider *slider;
  22. Widget *widget;
  23. int cur_width;
  24.  
  25. };
  26.  
  27. #endif


هذا هو الملف الرأس للنافذة الرئيسية للمثال.

  1. private:
  2. QSlider *slider;
  3. Widget *widget;
  4. int cur_width;


سيكون معنا أداتين في الواجهة الرئيسية للمستخدم للنافذة. و هما مزلاج slider و هذا معرّف مسبقاً من حقيبة الأدوات الرئيسية الموجودة بـ Qt و الأداة المصممة بواسطتنا نحن و بالمواصفات المطلوبة. المتغير cur_width سيحتفظ بالقيمة الحالية من المزلاج slider. هذه القيمة ستُستعمل عند تلوين الأداة المصممة بواسطتنا.

[left]burning.cpp[/left]
  1. #include 'burning.h'
  2. #include <QApplication>
  3. #include <QPainter>
  4. #include <QVBoxLayout>
  5. #include <QFrame>
  6. #include <QPushButton>
  7.  
  8. Burning::Burning(QWidget *parent)
  9. : QFrame(parent)
  10. {
  11. slider = new QSlider(Qt::Horizontal , this);
  12. slider->setMaximum(750);
  13. slider->setGeometry(50, 50, 130, 30);
  14.  
  15. connect(slider, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
  16.  
  17. QVBoxLayout *vbox = new QVBoxLayout(this);
  18. QHBoxLayout *hbox = new QHBoxLayout();
  19.  
  20. vbox->addStretch(1);
  21.  
  22. widget = new Widget(this);
  23. hbox->addWidget(widget, 0);
  24.  
  25. vbox->addLayout(hbox);
  26.  
  27. setLayout(vbox);
  28.  
  29. }
  30.  
  31. void Burning::valueChanged(int val)
  32. {
  33. cur_width = val;
  34. widget->repaint();
  35. }
  36.  
  37. int Burning::getCurrentWidth()
  38. {
  39. return cur_width;
  40. }


هنا سنقوم ببناء النافذة الرئيسية للمثال.
  1. void Burning::valueChanged(int val)
  2. {
  3. cur_width = val;
  4. widget->repaint();
  5. }


عندما نغير قيمة المزلاج, سنحفظ القيمة الجديدة و يتم إعادة تلوين الأداة المصممة بواسطتنا.

[left]widget.h[/left]
  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3.  
  4. class Burning;
  5.  
  6. #include <QFrame>
  7.  
  8. class Widget : public QFrame
  9. {
  10. Q_OBJECT
  11.  
  12. public:
  13. Widget(QWidget *parent = 0);
  14.  
  15. protected:
  16. void paintEvent(QPaintEvent *event);
  17.  
  18. public:
  19. QWidget *m_parent;
  20. Burning *burn;
  21.  
  22. };
  23.  
  24. #endif


هذا الملف الرأس الخاص بالأداة المصممة بواسطتنا The burning widget.

  1. public:
  2. QWidget *m_parent;
  3. Burning *burn;


نخزن مؤشر في الأداة الحاضنة الأم. و نحصل على العرض الحالي لهذه الأداة عن طريق هذا المؤشر.

[left]widget.cpp[/left]
  1. #include 'widget.h'
  2. #include 'burning.h'
  3. #include <QPainter>
  4. #include <QFrame>
  5. #include <QHBoxLayout>
  6. #include <QTextStream>
  7.  
  8.  
  9. QString num[] = { '75', '150', '225', '300', '375', '450', '525', '600', '675' };
  10. int asize = sizeof(num)/sizeof(num[1]);
  11.  
  12. Widget::Widget(QWidget *parent)
  13. : QFrame(parent)
  14. {
  15. m_parent = parent;
  16. setFrameShape(QFrame::StyledPanel);
  17. setMinimumHeight(30);
  18. }
  19.  
  20. void Widget::paintEvent(QPaintEvent *event)
  21. {
  22.  
  23. QPainter painter(this);
  24. painter.setPen(QColor('#d4d4d4'));
  25.  
  26. int width = size().width();
  27.  
  28.  
  29. Burning *burn = (Burning *) m_parent;
  30. int cur_width = burn->getCurrentWidth();
  31.  
  32.  
  33. int step = (int) qRound(width / 10.0);
  34.  
  35.  
  36. int till = (int) ((width / 750.0) * cur_width);
  37. int full = (int) ((width / 750.0) * 700);
  38.  
  39.  
  40. if (cur_width >= 700) {
  41.  
  42. painter.setPen(QColor(255, 255, 184));
  43. painter.setBrush(QColor(255, 255, 184));
  44. painter.drawRect(0, 0, full, 30);
  45. painter.setPen(QColor(255, 175, 175));
  46. painter.setBrush(QColor(255, 175, 175));
  47. painter.drawRect(full, 0, till-full, 30);
  48.  
  49. } else {
  50.  
  51. painter.setPen(QColor(255, 255, 184));
  52. painter.setBrush(QColor(255, 255, 184));
  53. painter.drawRect(0, 0, till, 30);
  54.  
  55. }
  56.  
  57. painter.setPen(QColor(90, 80, 60));
  58. for ( int i=1; i <= asize; i++ ) {
  59.  
  60. painter.drawLine(i*step, 0, i*step, 6);
  61. QFont newFont = font();
  62. newFont.setPointSize(7);
  63. setFont(newFont);
  64.  
  65. QFontMetrics metrics(font());
  66.  
  67. int w = metrics.width(num[i-1]);
  68. painter.drawText(i*step-w/2, 19, num[i-1]);
  69.  
  70. }
  71.  
  72. QFrame::paintEvent(event);
  73.  
  74. }


هنا نلوّن أداتنا المصممة الجديدة burning widget و نلوّن المستطيل الخاص بها, و الخطوط الأفقية و الأعداد التي ستكون معيار و درجة الحرق.

  1. setFrameShape(QFrame::StyledPanel);


نستعمل الأداة (الصنف QFrame ) ليكون قاعدة لأداتنا المصممة الجديدة.

  1. Burning *burn = (Burning *) m_parent;
  2. int cur_width = burn->getCurrentWidth();


نحصل على قيمة المتغير cur_width.

  1. QFontMetrics metrics(font());
  2.  
  3. int w = metrics.width(num[i-1]);
  4. painter.drawText(i*step-w/2, 19, num[i-1]);


هذه الشيفرة تقوم برسم الأعداد. نستعمل مصفوفات الخطوط لنحصل على عرض النص.

  1. QFrame::paintEvent(event);


الآن نحضر الحدث الخاص للتلوين لنضيفها إلى الأداة الأم .

[left]main.cpp[/left]
  1. #include 'burning.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 = 370;
  12. int HEIGHT = 200;
  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. }
  25.  
  26.  
  27. int main(int argc, char *argv[])
  28. {
  29. QApplication app(argc, argv);
  30. Burning window;
  31.  
  32. window.setWindowTitle('The Burning widget');
  33. window.show();
  34. center(window);
  35.  
  36. return app.exec();
  37. }


هذا الملف الرئيسي...

و هذه صورة للنافذة الرئيسية في المثال تحتوي على المزلاج و الأداة المصممة بواسطتنا المرقّمة و المدرّجة بمواصفات خاصة و اسمها The Burning Widget.



تمت طباعة الدرس من موقع مكتبة الدروس
http://qt-ar.org/lessons/show40.html