الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

System Tray

بدأه ahmed_youssef في 3 يوليو 2008 · 2 رد · 1,876 مشاهدة · في قسم Cross Platform GUI Libraries العام
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

سلام عليكم

فى برنامج فى ال Examples تبع ال QT بإسم systray هتلقيه تحت ال QT/Examples/Desktop ودا تحليل المثال

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

شكل ال Application

15riqub.jpg

لاحظ ال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 .. ندخل فى ال implementation ال code للميثودز و ال members

SAVE

افتح file جديد وسميه window.cpp

لازم نستدعى فيه

#include "window.h"

لأن فيه التصميم بتاع ال class اللى هنملاه

ونستدعى

#include <QtGui>

عشان ال GUI Components

نبدأ فى إننا نعمل implement لل 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 وشغل!

تم تعديل هذه المشاركة بواسطة ahmed_youssef في 3 يوليو 2008 في 01:39

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#2

مشكور اخي العزيز ahmed_youssef

بس كفكرة عامة للأعضاء الفكرة العامة للبرنامج وضع ايقونة في شريط المهام

بإستخدام الصف QSystemTrayIcon

وأهم أوامرها هو ما استخدمه البرنامج

وهو setIcon لإضافة ايقونة

setToolTip لإضافة نص عند مرور الفارة على الأيقونة

showMessage لمشاهدة رسالة تطلع تلقائيا من الأيقونة وتقدر تحدد أيقونة الرسالة بواسطة ثابت رقمي وبقي آخر أهم الدوال وهي setContextMenu لإضافة قائمة للعمل

شاكرا مرة أخرى الصديق ahmed_youssef والسلام عليكم

بسم الله الرحمن الرحيم

مدونة دوال

كيوتي العربي

#3

عجيب انى اشرح المثال من غير ماقول هدفه مش كدا ههههههههههههه ؟

شكرا مصفوفة على مرورك والإضافة

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

مواضيع مشابهة