قبل از اینکه در مورده اسلات و سیگنال حرف بزنیم اول بریم یه ذره دعوا ببینیم حال کنیم!
تو یه اتاق چند تا لات و لوت موجود هستن! یکی محکم میزنه تو سره یکی دیگه! (شپلق :دی) مضروب میگه آی منو زدن! بعضیا اصلا اهمیت نمیدن! بعضیا بالا خواه طرف درمیانو میان که طرفو بزننو انتقام دوستشونو بگیرن و عکس العمل نشون میدن! بعضی ها هم میگن آی اینو زدن تا یک سری دیگه رو خبر کنن!
خب بسه دیگه مگه کارو زندگی نداری وایسادی داری دعوا نگا میکنی؟ کیوت کار کن بچه! خب حالا وقتی میایم تو دنیای کیوت به "آی منو زدن" یا "آی اینو زدن" میگن سیگنال! یعنی خبر چین! خبر چین خودش کاری نمیکنه فقط کسی رو از اتفاقی خبر دار میکنه.دقیقا این کاریه که سیگنال میکنه یعنی وقتی مثلا یک دکمه ای رو کلیک میکنین سیگنال کلیک شروع به دادو بیداد کردن میکنه و هر رخدادی که مربوط به کلیک دکمه هست رو با خبر میکنه. خب اونایی که بالا خواه دراومدن و کاری انجام دادن؛ به اون کارشون میگیم اسلات!
شما میتونین سیگنالهای موجود یک شیء رو به یک اسلات یا چندین اسلات وصل کنید؛ حتی میتونید یک سیگنال رو به یک سیگنال دیگه وصل کنید (وقتی میگه «آی منو زدن» یکی دیگه میگه «آی اینو زدن»!)؛ حتی میتونین این ارتباطات رو قطع کنین! یعنی اینکه وقتی مضروب داد میزنه که «آی منو زدن» دیگه هیچکی اهمیت نده! (توجه کنین که سیگنال از بین نرفته! بابا مگه نمیشنوی طرف داره داد بیداد میکنه هنوز، ولی کسی عکس العملی نشون نمیده!)
البته شما میتونین خودتون یک سیگنال در موقع نیاز به یک کلاس اضافه کنین و در موقع استفاده اونو emit (پخش) کنید (یعنی شروع به خبر چینی کنه!)
خب حالا بیاین یه مثال بزنیم و بریم جلو:
اول یک فایل متنی درست کنین و کدای زیر رو بزنین!:
#include <QObject>
class myClass:public QObject
{
Q_OBJECT
public:
myClass() { cnt=0; }
int getValue() const {return cnt;}
public slots:
void setValue(int);
signals:
void valueChanged(int newValue);
private:
int cnt;
};
این فایل رو با نامه myHeader.h ذخیره کنین
ماکرو مجموعه ای ازچندین دستورالعمله که همگی در یه دستور تعبیه شدن. این یکه سازی باعث کم خطاتر شدن برنامه میشه؛ کیوت هم یه ماکرو داره به نام Q_OBJECT که هر کلاسی که قصد تعریف سیگنالها و اسلاتهای مخصوص به خود رو داره یا قصد استفاده از امکانات meta-object کیوت رو داره باید این ماکرو رو تو قسمته private کلاسش قرار بده. پس چرا ما اون بالا گذاشتیم؟ نابغه جان حالته پیش فرض دسترسی اعضا کلاس در موقع تعریفشان private هست، پس الان Q_OBJECT هم Private هست. میتونستیم اون پایین تو قسمته private هم بنویسیمش ولی اینطوری خوانا تره! ۱۰۰ بار گفتم ++C بلد نیستی غلط میکنی میای سراغه کیوت! :دی
خوب، مقدار اولیه عضو cnt رو تو سازنده برابر صفر میگذاریم. یک تابع هم به نام getValue که مقدار حال حاضر cnt رو بر میگردونه و یک اسلات که یک مقدار صحیح میگیره تعریف کردیم. میبینین که فقط یه کلمه کلیدی slot رو داره و ادامش دیگه مثل یک تابع معمولیه زبان ++C هستش بعدشم با کلمه کلیدی signals سیگنالمون رو تعریف کردیم. سیگنالها باید از نوع void باشن و داخل پرانتز هم نوع متغیری که قراره به اسلاتی که بهش وصل بشه رو هم وارد میکنیم.
خب حالا یک فایل متنی دیگه درست کنید و کد زیر رو بزنین:
#include "myHeader.h"
void myClass::setValue(int NV)
{
if (NV!=cnt)
{
cnt=NV;
emit valueChanged(NV);
}
}
خوب تو این تکه کد، داریم اسلاتمون رو پیاده سازی میکنیم .همون طور که میبینین تابع ما چک میکنه که اگه مقدار جدید با مقدار قدیمی cnt برابر نبود اونوقت مقدار جدید رو بریز داخله cnt و بعد با کلمه کلیدی emit سیگنال رو پخش میکنیم (بهش میگیم که داد بزنه!) و به سیگنال مقدار جدید تغییر یافته رو پاس میدیم
یک سوال! اگه این چک رو انجام ندیم چی میشه؟
فرض کنین که اسلات setValue این طوری بود:
void myClass::setValue(int NV)
{
cnt=NV;
emit valueChanged(NV);
}
هر بار که اسلات setValue رو صدا میکنیم مقدار ورودی را در cnt میریزه و سیگنال valueChanged رو صدا میزنه یعنی مقدار تغییر کرده! حالا اگه سیگنال valueChanged یک شیء به اسلات setValue وصل باشه دوباره setValue رو صدا میزنه، در صورتی که مقدار تغییر نکرده و در یک حلقه نامتناهی این صدا زدن ها قرار میگیره! خب با یک شرط ساده که آیا مقدار تغییر کرده یا نه، میتونیم از گفتن خبرهای تکراری خبر چینا جلوگیری کنیم!
خب این فایل رو هم با نام myHeaderDeploy.cpp در مسیری که myHeader هست، ذخیره کنین.
یک فایل جدید دیگه درست کنین و کد زیر رو بزنین:
#include <QObject>
#include "myHeader.h"
#include <iostream>
int main()
{
myClass a,b;
QObject::connect(&a,SIGNAL(valueChanged(int)),
&b,SLOT(setValue(int)));
a.setValue(2567);
std::cout<<b.getValue()<<std::endl;
return 0;
}
همونطور که میبینین دو تا شیء از کلاسمون درست کردیم.
حالا میخوایم که وقتی مقدار cnt شیء a رو تغییر میدیم مقدار cnt شیء b هم همون مقدار cnt شیء a بشه. پس باید سیگنال valueChanged (که هر بار مقدار cnt تغییر میکنه خبر چینی میکنه!) شیء a رو به اسلات شیء b وصل کنیم. برای این کار از QObject::connect استفاده میکنیم که چهار پارامتر دریافت میکنه. اولی اشاره گری هستش که به شیء فرستندش اشاره میکنه (یعنی کدوم شیء هستش که میخوایم سیگنالی ازش رو به یک شیء دیگه وصل کنیم). دومین پارامتر اون سیگنالیه که قرار وصل بشه که اسم و نوع پارامترشو داخل پرانتز همراه با کلمه SIGNAL میفرستیم. پارامتر سوم به شیء گیرنده اشاره میکنه (یعنی کدوم شیء هست که میخوایم سیگنالی رو بهش وصل کنیم). پارامتر آخر اون اسلاتیه که قراره با پخش سیگنال به شیء b صدا زده بشه که نام اسلات رو با نوع پارامتری که میگیره داخل پرانتز با کلمه SLOT مینویسیم. خب حالا تابع setValue شیء a را صدا میزنیم و مقدار cnt را برابر 2567 قرار میدیم .میدونیم که تابع setValue در صورت تغییر مقدار سیگنال valueChanged را پخش میکنه و میدونیم که این سیگنال متصل به اسلات setValue شیء b هستش پس مقدار cnt شیء b هم تغییر میکنه. در آخره برنامه برای تائید این موضوع مقدار cnt شیء b را چاپ میکنیم.
بعدا که پیش بریم تو برنامه هایی که بهتون نشون میدیم میتونین به همین روال مثلا کلیک شدن یک دکمه(که یک سیگنال از پیش طراحی شده کیوت هستش)رو به پاک کردن یک آیتم از یک لیست یا هر اسلات دیگه ای وصل کنین.
حالا این فایل رو با هر اسمی که دوست دارین با پسوند cpp ذخیره و برنامتون رو کامپایل کنین
2 نظر:
خوبه آدم وقتی داره یه مطلبی ارائه میده، یه مقدار ادب هم داشته باشه.
آخه کجای دنیا دیدی یه مطلب با این ارزش رو اینقدر بچه گونه بیان کنن.
اگه میشه دفعه ی بعد یه مقدار با ادب مطالبتون رو بیان کنید.
حالا باز تو خوبی اون یکی که مجنون شده نه دیگه مطلب میزاره نه چیزی!!!
شما معلومه تا حالا چند تا داکیومنت کدباز نخوندی جیگر!بیشترشون همین طورین!یکی از دلیل این کاره ما پیوند دنیای واقعی با دنیای نرم افزاره!
ارسال يک نظر