إعـــــــلان

تقليص
لا يوجد إعلان حتى الآن.

SysTray

تقليص
X
 
  • تصفية - فلترة
  • الوقت
  • عرض
إلغاء تحديد الكل
مشاركات جديدة

  • SysTray

    شرح التعامل مع SystemTray


    انا بدأت فى ال QT مع ال C++ زى مانتو عارفين وبصراحة من افضل الطرق للتعليم هو إنك تطلع على ال Source code لأى برنامج هيفيد الواحد كتير .. ندخل فى الموضوع بإختصار فى برنامج فى ال Examples تبع ال QT بإسم systray هتلقيه تحت ال QT/Examples/Desktop

    اول شئ ملف الresources ودا مضاف فيه بعض الصور اللى هتستخدم فى البرنامج

    ثانيا فى تكنيك فى البرمجة بال C++ وهو إنك تكتب ال class من غير ماتعمل implement لل methods اللى فيه وتعمل ال implementation بتاعها بعدين ودا اللى إحنا هنعمله

    شكل ال Application

    لاحظ الApplication متقسم إلى
    2 GroupBoxes
    الأول هو TrayIcon وبيشمل
    Label بإسم Icon:
    و ComboBox فيه كذا Item زى Heart و Bad و Thrash
    و CheckBox -> Show icon

    التانى بيشمل
    Label مكتوب عليه type
    و ComboBox فيه الصور المستخدمة فى ال MessageBoxes ك informations
    و Label مكتوب عليه Duration
    و SpinBox
    وبعد كدا Label بإسم title
    وامامه LineEdit
    وتحته Label مكتوب عليه body
    وتحته RichEdit وفيه هيتكتب الرسالة اللى هتظهر !
    واخيرا PushButton مكتوب عليه Show Message


    نبدأ الشغل ..
    افتح ال IDE اللى هتكتب فيها انا حاليا على Dev-C++
    اولا اعمل ملف لل header وليكن window.h
    كود:
    #ifndef WINDOW_H
    #define WINDOW_H
    هنضيف ال headers اللى هنستخدمها وهى ال Qwidget لأن دى ال Widget اللى هنشتق منها ال Class تبعنا
    وال QsystemTrayIcon عشان نستخدم ال TrayIcon ...
    كود:
    #include <QSystemTrayIcon>
    #include <Qwidget>
    بنعلن عن ال Classes اللى هنستخدمها
    كود:
    class QAction;
    class QCheckBox;
    class QComboBox;
    class QGroupBox;
    class QLabel;
    class QLineEdit;
    class QMenu;
    class QPushButton;
    class QSpinBox;
    class QtextEdit;
    الQAction هى كل مايتم إضافته لل Menu

    ال Class بتاعنا
    كود:
    class Window : public Qwidget
    لاحظ إنه إشتق من ال Qwidget

    لازم إذا هيكون لل Class اللى بتاعك ال SLOTS/SIGNALS خاصة بيه لازم ال Q_OBJECT marco

    ال Constructor ودالة تانية هنختص إنها تبقة مسؤلة عن ال Visibility هنخليهم public
    كود:
    public:
        Window();
    
        void setVisible(bool visible);
    هنضيف handler لل CloseEvent
    كود:
    protected:
        void closeEvent(QCloseEvent *event);
    نعلن عن ال SLOTS
    كود:
    private slots:
        void setIcon(int index);
        void iconActivated(QSystemTrayIcon::ActivationReason reason);
        void showMessage();
        void messageClicked();
    الميثودز التالية هى اللى هنستخدمها فى عمل ال iconGroupBox وال MessageGroupBox وال Actions بتاعت ال menu وال trayicon
    
    private:
        void createIconGroupBox();
        void createMessageGroupBox();
        void createActions();
        void createTrayIcon();
    الميمبرز اللى هنستخدمهم ولكن من غير ماتعمل اى initialization
    كود:
      QGroupBox *iconGroupBox;
        QLabel *iconLabel;
        QComboBox *iconComboBox;
        QCheckBox *showIconCheckBox;
    
        QGroupBox *messageGroupBox;
        QLabel *typeLabel;
        QLabel *durationLabel;
        QLabel *durationWarningLabel;
        QLabel *titleLabel;
        QLabel *bodyLabel;
        QComboBox *typeComboBox;
        QSpinBox *durationSpinBox;
        QLineEdit *titleEdit;
        QTextEdit *bodyEdit;
        QPushButton *showMessageButton;
    
        QAction *minimizeAction;
        QAction *maximizeAction;
        QAction *restoreAction;
        QAction *quitAction;
    
        QSystemTrayIcon *trayIcon;
        QMenu *trayIconMenu;
    ننهى التعريف
    كود:
    };
    
    #endif
    كدا إحنا عملنا التصميم المبدأى لل Class .. ندخل فى ال implementing ال code للميثودز و ال members

    SAVE

    افتح file جديد وسميه window.cpp
    لازم نستدعى فيه
    كود:
    #include "window.h"
    لأن فيه التصميم بتاع ال class اللى هنملاه
    ونستدعى
    كود:
    #include <QtGui>
    عشان ال GUI Components

    نبدأ فى إننا نعمل implementing لل Constructor زيه زى اى function !
    كود:
    Window::Window()
    {
        createIconGroupBox();
        createMessageGroupBox();
    
        iconLabel->setMinimumWidth(durationLabel->sizeHint().width());
    
        createActions();
        createTrayIcon();
    
        connect(showMessageButton, SIGNAL(clicked()), this, SLOT(showMessage()));
        connect(showIconCheckBox, SIGNAL(toggled(bool)),
                trayIcon, SLOT(setVisible(bool)));
        connect(iconComboBox, SIGNAL(currentIndexChanged(int)),
                this, SLOT(setIcon(int)));
        connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
        connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
                this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
    
        QVBoxLayout *mainLayout = new QVBoxLayout;
        mainLayout->addWidget(iconGroupBox);
        mainLayout->addWidget(messageGroupBox);
        setLayout(mainLayout);
    
        iconComboBox->setCurrentIndex(1);
        trayIcon->show();
    
        setWindowTitle(tr("Systray"));
        resize(400, 300);
    }
    لاحظ بما إنه ال Constructor فلازم يتم إنهاء التصميم الخاص بال GUI فيه فهنستدعى الدالتين اللى عايزينهم يصممو ال GUI قبل مانكتبهم حتى :D
    كود:
        createIconGroupBox();
        createMessageGroupBox();
    وكمل الباقى ال Label وال CheckBox وباقى ال members
    لاحظ
    كود:
    connect(showMessageButton, SIGNAL(clicked()), this, SLOT(showMessage()));
        connect(showIconCheckBox, SIGNAL(toggled(bool)),
                trayIcon, SLOT(setVisible(bool)));
        connect(iconComboBox, SIGNAL(currentIndexChanged(int)),
                this, SLOT(setIcon(int)));
        connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
        connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
                this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
    هنا تم ربط ال SLOTS بال SIGNALS .. إذا مش تعرف الفرق حاول تقرا اى توتريل

    ال QVBoxLayout بيستخدم فى عمل GUI Layout Vertically
    و YES ال QHBoxLayout بيستخدم فى عمله Horizontally
    و YES تانى ال QGBoxLayout بيستخدم فى عمله بإستخدام GRID !
    شكلك شاطر ياعم هههههههههه

    ال setWindowsTitle بتستخدم فى وضع ال Title على ال Window!
    ال resize لتحجيم ال Window

    ال tr عشان لو ناوى تترجم برنامجك للغة تانية فى المستقبل ان شاء الله :D ويفضل إنك تضيفها على كل string هيظهر على اى window !


    وبعد كدا ال setVisible method
    كود:
    void Window::setVisible(bool visible)
    {
        minimizeAction->setEnabled(visible);
        maximizeAction->setEnabled(!isMaximized());
        restoreAction->setEnabled(isMaximized() || !visible);
        QWidget::setVisible(visible);
    }
    وكل اللى فيها هو مراعاة ال ال items اللى فى ال trayicon's context menu تكون enabled او disabled حسب حال ال Window

    كود:
    void Window::setIcon(int index)
    {
        QIcon icon = iconComboBox->itemIcon(index);
        trayIcon->setIcon(icon);
        setWindowIcon(icon);
    
        trayIcon->setToolTip(iconComboBox->itemText(index));
    }
    ال setIcon هتستخدم ال index من ال iconComboBox عشان تحدد الicon اللى هتاخدها ال tray!
    و setWindowIcon بتحدد ال icon اللى هتاخدها ال window

    كود:
    void Window::showMessage()
    {
        QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(
                typeComboBox->itemData(typeComboBox->currentIndex()).toInt());
        trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon,
                              durationSpinBox->value() * 1000);
    }
    هى ال method المسئولة عن ال title وال body لل trayicon message
    كود:
    void Window::messageClicked()
    {
        QMessageBox::information(0, tr("Systray"),
                                 tr("Sorry, I already gave what help I could.\n"
                                    "Maybe you should try asking a human?"));
    }
    إذا تم الضغط على ال trayicon message هيظهر MessageBox فيه رسالة
    "Sorry, I already gave what help I could.\n"
    "Maybe you should try asking a human?"


    فاكر ال createIconGroupBox وال createMessageGroupBox ?اللى إستخدمناهم فى ال Constructor ومش كاتبين فيها حاجة غير ال prototype ?
    ادينا هنكتبهم
    كود:
    void Window::createIconGroupBox()
    {
        iconGroupBox = new QGroupBox(tr("Tray Icon"));
    
        iconLabel = new QLabel("Icon:");
    
        iconComboBox = new QComboBox;
        iconComboBox->addItem(QIcon(":/images/bad.svg"), tr("Bad"));
        iconComboBox->addItem(QIcon(":/images/heart.svg"), tr("Heart"));
        iconComboBox->addItem(QIcon(":/images/trash.svg"), tr("Trash"));
    
        showIconCheckBox = new QCheckBox(tr("Show icon"));
        showIconCheckBox->setChecked(true);
    
        QHBoxLayout *iconLayout = new QHBoxLayout;
        iconLayout->addWidget(iconLabel);
        iconLayout->addWidget(iconComboBox);
        iconLayout->addStretch();
        iconLayout->addWidget(showIconCheckBox);
        iconGroupBox->setLayout(iconLayout);
    }
    لاحظ إن انك تقدر تضيف icon فى combobox بإستخدام Qicon كأول بارميتر وتحدد فيه مسار الصورة و ويليه ال label اللى عايزه يظهر جمبها

    واحد هيسأل فين مسار الصورة ؟ هجاوبك حالا بعد ماعلق على ال Layout
    بنستخدم addWidget عشان نضيف اى widget ل Layout سواء Horizontal او Vertical او حتى GRID
    اى layout ليه ميثود addLayout بتستخدم فى إننا نضيف اى Layout لل Layout الحالى .. هتشوفها بعدين
    كود:
    void Window::createMessageGroupBox()
    {
        messageGroupBox = new QGroupBox(tr("Balloon Message"));
    
        typeLabel = new QLabel(tr("Type:"));
    
        typeComboBox = new QComboBox;
        typeComboBox->addItem(tr("None"), QSystemTrayIcon::NoIcon);
        typeComboBox->addItem(style()->standardIcon(
                QStyle::SP_MessageBoxInformation), tr("Information"),
                QSystemTrayIcon::Information);
        typeComboBox->addItem(style()->standardIcon(
                QStyle::SP_MessageBoxWarning), tr("Warning"),
                QSystemTrayIcon::Warning);
        typeComboBox->addItem(style()->standardIcon(
                QStyle::SP_MessageBoxCritical), tr("Critical"),
                QSystemTrayIcon::Critical);
        typeComboBox->setCurrentIndex(1);
    
        durationLabel = new QLabel(tr("Duration:"));
    
        durationSpinBox = new QSpinBox;
        durationSpinBox->setRange(5, 60);
        durationSpinBox->setSuffix(" s");
        durationSpinBox->setValue(15);
    
        durationWarningLabel = new QLabel(tr("(some systems might ignore this "
                                             "hint)"));
        durationWarningLabel->setIndent(10);
    
        titleLabel = new QLabel(tr("Title:"));
    
        titleEdit = new QLineEdit(tr("Cannot connect to network"));
    
        bodyLabel = new QLabel(tr("Body:"));
    
        bodyEdit = new QTextEdit;
        bodyEdit->setPlainText(tr("Don't believe me. Honestly, I don't have a "
                                  "clue.\nClick this balloon for details."));
    
        showMessageButton = new QPushButton(tr("Show Message"));
        showMessageButton->setDefault(true);
    
        QGridLayout *messageLayout = new QGridLayout;
        messageLayout->addWidget(typeLabel, 0, 0);
        messageLayout->addWidget(typeComboBox, 0, 1, 1, 2);
        messageLayout->addWidget(durationLabel, 1, 0);
        messageLayout->addWidget(durationSpinBox, 1, 1);
        messageLayout->addWidget(durationWarningLabel, 1, 2, 1, 3);
        messageLayout->addWidget(titleLabel, 2, 0);
        messageLayout->addWidget(titleEdit, 2, 1, 1, 4);
        messageLayout->addWidget(bodyLabel, 3, 0);
        messageLayout->addWidget(bodyEdit, 3, 1, 2, 4);
        messageLayout->addWidget(showMessageButton, 5, 4);
        messageLayout->setColumnStretch(3, 1);
        messageLayout->setRowStretch(4, 1);
        messageGroupBox->setLayout(messageLayout);
    }
    نكمل .. هنضع ال code الخاص ب create actions
    كود:
    void Window::createActions()
    {
        minimizeAction = new QAction(tr("Mi&nimize"), this);
        connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
    
        maximizeAction = new QAction(tr("Ma&ximize"), this);
        connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
    
        restoreAction = new QAction(tr("&Restore"), this);
        connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
    
        quitAction = new QAction(tr("&Quit"), this);
        connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
    }
    عملنا كل اكشن منهم وربطنا ال SIGNAL و SLOT
    عمل ال trayicon
    كود:
    void Window::createTrayIcon()
    {
        trayIconMenu = new QMenu(this);
        trayIconMenu->addAction(minimizeAction);
        trayIconMenu->addAction(maximizeAction);
        trayIconMenu->addAction(restoreAction);
        trayIconMenu->addSeparator();
        trayIconMenu->addAction(quitAction);
    
        trayIcon = new QSystemTrayIcon(this);
        trayIcon->setContextMenu(trayIconMenu);
    }
    لاحظ إن جزئية عمل ال trayicon متقسمة لجزئين
    1- عمل ال Contextmenu الخاصة بال trayicon وهي trayIconMenu وضفنا فيها ال Actions اللى عملناها بالميثود السابقة بإستخدام addAction method
    وال addSeperator بتضيف Seperator فى ال Menu


    نعمل Object من ال trayIcon ونضيف ال contextMenu الخاصة بيها وهىtrayIconMenu بإستخدام
    setContextMenu

    بخصوص موضوع ال resources .. الصور موجودة عندك فى folder إسمه images ومتظبط ال resources file
    systray.qrc

    اعمل ملف main.cpp وهو هيكون ال Entry point لل Application بتاعنا
    كود:
    #include "window.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        if (!QSystemTrayIcon::isSystemTrayAvailable()) {
            QMessageBox::critical(0, QObject::tr("Systray"),
                                  QObject::tr("I couldn't detect any system tray "
                                              "on this system."));
            return 1;
        }
    
        Window window;
        window.show();
        return app.exec();
    }
    فى حال لو ال SystemTray غير متاح عندك هيطلع Error ويخرج من البرنامج غير كدا هيعمل Object من ال Window Class
    بنستخدم show method عشان نخليه visible
    وال return هو تنفيذ ال Application
    بعد ماتخلص
    كود:
    ~> qmake -project
    ~> qmake systray.pro
    ~> make
    افتح folder release وشغل!
    البرنامج مرفق

    بس كدا إيدى وجعتنى :S
    الملفات المرفقة
    التعديل الأخير تم بواسطة StrikerX; الساعة 26-05-2008, 09:27 AM.
    Programming-Fr34ks[dot]NET
    Ma Weblog
    ابدأ بتعلم Python | Ruby
    كتاب البايثون متوافر الآن
    لا اتواجد بهذا المنتدى ... للإتصال

  • #2
    المشاركة الأصلية بواسطة StrikerX مشاهدة المشاركة
    بس كدا إيدى وجعتنى :S
    سلامت ايدك ياحنييين

    تسلم StrikerX على المقال والشرح الرائع بالفعل مواضيع يتم ارشفتهاا والاستفاده لاحقاً ..

    bad3r

    Twitter
    : @Linux4SA

    تعليق


    • #3
      تمام التمام
      ^_^
      موقع وثائق لينوكس العربية
      موقع مختص بتوثيق لينكس

      ((شاركنا بمواضيعك، أفكارك، إقتراحاتك، ومساعدتك لنا هي أساس إستمرارنا ... فلا تبخل علينا بما لديك ولو كان بنظرك قليل، فهو بنظرنا الكثير))





      تعليق


      • #4
        تمـام يا ابو حميـد وطبعـا انا مليش في السـي واخواتهـا
        بـس درس حلو يا جميـل وبالتوفيق

        تعليق


        • #5
          ما بعرف اذا هذا ينطبق على ويندوز كمان، ولكن لو كان لينوكس، يمكنك تغيير الثيم الخاص بالبرنامج عند تشغيله بالطريقة التالية:

          كود PHP:
          programname -style <style_name
          والـ style name يكون احد الاستايلات المتوفرة في QT Designer
          موقع وثائق لينوكس العربية
          موقع مختص بتوثيق لينكس

          ((شاركنا بمواضيعك، أفكارك، إقتراحاتك، ومساعدتك لنا هي أساس إستمرارنا ... فلا تبخل علينا بما لديك ولو كان بنظرك قليل، فهو بنظرنا الكثير))





          تعليق


          • #6
            شكرا على المرور ياجماعة .. بخصوص موضوع ال styles الخاصة بالبرنامج فالمتوافر
            Windows, Windows XP, Motif, CDE, Plastique and Cleanlooks

            وطريقة الإستخدام زى ماوضحها الأخ مسلم
            Programming-Fr34ks[dot]NET
            Ma Weblog
            ابدأ بتعلم Python | Ruby
            كتاب البايثون متوافر الآن
            لا اتواجد بهذا المنتدى ... للإتصال

            تعليق


            • #7
              رائع جدا StrikerX ،،

              بس في ملاحظة مهمة شوي للناس المتعودة على سي++ ،،
              المتغيرات الموجودة داخل المحدد private ، تحجز داخل ال heap !!
              وطبعا لا تحذف الا باستخدام delete ، لكن Qt تقوم بحذف جميع الابناء لل widget الاب

              وهكذا تريحنا من استخدام delete لكل مؤشر .

              وبالنسبة لتغيير الاستايل ،، فممكن من خلال سطر الاوامر ، او من خلال الدالة
              ...
              QApplication::setStyle();
              على ما اذكر ،،


              تحياتي لك اخي ،، واتمنى ان تكمل المشوار ،،
              الى اللقاء ،،

              تعليق


              • #8
                شكرا SudaNix على المرور والإضافة
                Programming-Fr34ks[dot]NET
                Ma Weblog
                ابدأ بتعلم Python | Ruby
                كتاب البايثون متوافر الآن
                لا اتواجد بهذا المنتدى ... للإتصال

                تعليق

                يعمل...
                X