آموزش توابع Qt قسمت هشتم
|
2004-09-06, 01:25 AM,
ارسال : #1
|
|||
|
|||
آموزش توابع Qt قسمت هشتم
فصل هشتم : Preparing for Battle
دراين مثال، ما اولين شيء سفارشي را كه مي تواند خود را با رنگ و شكل پر كند معرفي مي كنيم. ما همچنين يك رابط صفحه كليد مفيد را نيز اضافه مي كنيم ( با دو خط كد نويسي ). [ltr]lcdrange.h[/ltr] [ltr] کد : #ifndef LCDRANGE_H [ltr]lcdrange.cpp [/ltr] [ltr] کد : #include “lcdrange.h” [ltr]cannon.h[/ltr] [ltr] کد : #ifndef CANNON_H [ltr]cannon.cpp[/ltr] [ltr] کد : #include “cannon.h” [ltr]main.cpp[/ltr] [ltr] کد : #include <qapplication.h> بررسي خط به خط برنامه: فايل lcdrange.h بسيار به فايل lcdrange.h در فصل هفتم شبيه است. ما يك اسلات به آن اضافه كرده ايم : setRange ( ). [ltr] کد : void setRange ( int minVal, int maxVal ); با اينكار امكان تنظيم محدوده LCDRange را به آن اضافه كرده ايم. تا كنون، در 99..0 ثابت مانده است. فايل lcdrange.cpp در سازنده اش تغييري ايجاد شده است ( ما بعداًدرمورد آن بحث خواهيم كرد). [ltr] کد : void LCDRange::setRange ( int minVal , int maxVal ) تابع setRange ( ) محدوده اسلايدر را در LCDRange تعيين مي كند. بخاطراينكه ما تعيين كرده ايم كه شيء QLCDNumber هميشه دو عدد را نشان دهد، مي خواهيم محدوده ممكن minVal و maxVal را به 99.. 0 جهت پرهيز از سرريزي QLCDNumber تعيين كنيم. اگر آرگومانها غيرمجاز بودند، ما از تابع qWarning ( ) براي صادر كردن يك هشدار به كاربر و بازگشت اضطراري استفاده مي كنيم. qWarning ( ) تابعي شبيه به printf است كه بصورت پيش فرض خروجي خود را به stderr مي فرستد. اگر شما مي خواهيد ، مي توانيد توابع مديريت خطاي خود را توسط ::qInstallMsgHandler ( ) بكار گيريد. در فايل cannon.h ، شيء CannonField يك شيء سفارشي جديد است كه مي داند چگونه خود را نمايش دهد. [ltr] کد : class CannonField : public QWidget شيء CannonField ، شيء QWidget را به ارث مي برد، و ما از روشي مشابه LCDRange استفاده مي كنيم. [ltr] کد : int angle ( ) const { return ang; } عجالتاً، CannonField تنها شامل يك متغير angle است كه ما از آن بعنوان واسط استفاده مي كنيم، همانند روشي كه براي متغير value در LCDRange استفاده كرديم. [ltr] کد : protected : اين رخداد يكي از توابع زياد كنترل رخداد QWidget است كه ما با آن روبرو شده ايم. اين تابع مجازي ( virtual function ) زماني كه يك شيء نياز به بروزرساني داشته باشد توسط Qt فراخواني مي شود، به بيان ديگر چهره شيء را طراحي مي كند. فايل cannon.cpp : [ltr] کد : CannonField::CannonField ( QWidget *parent , const char *name ) : QWidget ( parent , name ) دوباره ، ما از روشي مشابه روشي كه براي LCDRange در فصل قبل استفاده كرديم در اينجا بكار مي گيريم. [ltr] کد : ang = 45; سازنده 45 درجه را به متغير angle به عنوان مقدار اوليه مي دهد و الگويي سفارشي را براي شيء در نظر مي گيرد. اين الگو از رنگ مشخص شده به عنوان پس زمينه استفاده مي كند و ديگر رنگها را بطور شايسته انتخاب كرده و بكار مي گيرد. ( تنها براي اين شيء رنگ پس زمينه و نوشته واقعاً استفاده شده است.) [ltr] کد : void CannonField::setAngle ( int degrees ) اين تابع مقدار زاويه را مشخص مي كند. ما محدوده اي مجاز از 70 .. 5 را انتخاب كرده ايم و بر طبق آن تعداد درجه هاي داده شده را تنظيم كرده ايم. ما مشخص نكرده ايم كه اگر زاويه جديد خارج از محدوده باشد هشداري صادر گردد. اگر زاويه جديد با قبلي يكي بود، ما فوراً باز مي گرديم. اين مهم است كه سيگنال angleChanged ( ) تنها زماني صادر شود كه واقعاً مقدار زاويه تغيير كرده باشد. سپس ما مقدار زاويه جديد را تعيين مي كنيم و شيء خود را دوباره رسم مي كنيم. تابع QWidget::repaint ( ) شيء را پاكيزه و دوباره ترسيم مي كند ( معمولاً آنرا با رنگ پس زمينه پر مي كند) و يك رخداد paint به شيء ارسال مي كند. اين نتايج در فراخواني يك رخداد paint شيء بدست مي آيد. سرانجام، ما سيگنال angleChanged() را براي اينكه به جهان بيروني بگوييم كه زاويه تغيير كرده است منتشر مي كنيم. كلمه كليدي emit براي Qt منحصر بفرد است و تركيبي قانوني از C++ نمي باشد. در حقيقت، يك ماكرو است. [ltr] کد : void CannonField::paintEvent ( QPaintEvent * ) اين اولين تلاش ما براي نوشتن يك دستگيره رخداد است. آرگومان رخداد شرحي از رخداد paint را شامل مي شود. QPaintEvent مختصات منطقه اي از شيء را كه بايد به روزرساني شود دارا مي باشد. بخاطر زمان و عجالتاً ما تنبل مي شويم و همه چيز را بروزرساني مي كنيم. كد ما مقدار زاويه را در مكان مشخص شده در شيء نشان مي دهد. ابتدا ما يك QString را همراه با مقداري متن و زاويه ايجاد مي كنيم. سپس يك QPainter را كه دراين شيء كار مي كند و از آن براي ترسيم رشته متني استفاده مي كنيم را ايجاد مي كنيم. بعداً دوباره به سراغ QPainter خواهيم آمد، اين شيء كارهاي زيادي مي تواند انجام دهد. فايل main.cpp: [ltr] کد : #include “cannon.h” ما كلاس جديد خود را ضميمه مي كنيم. [ltr] کد : class MyWidget : public QWidget در اين لحظه ما يك LCDRange تنها و يك CannonField را به شيء سطح بالاي خود اظافه مي كنيم. [ltr] کد : LCDRange *angle = new LCDRange ( this , “angle” ); در سازنده، ما LCDRange خود را ايجاد و تنظيم مي كنيم. [ltr] کد : angle -> setRange ( 5 , 70 ); LCDRange را طوري تنظيم مي كنيم كه درجه هاي بين 5 تا 70 را بپذيرد. [ltr] کد : CannonField *cannonField = new CannonField ( this , “cannonField” ); CannonField خود را ايجاد مي كنيم. [ltr] کد : connect ( angle , SIGNAL ( valueChanged ( int ) ) , cannonField , SLOT ( setAngle ( int ) ) ); دراينجا ما سيگنال valueChanged( ) از شيء LCDRange را به اسلات setAngle ( ) از CannonField متصل كرده ايم. اين كار باعث مي شود زماني كه كاربر روي LCDRange كاركند مقدار زاويه CannonField بروزرساني شود. همچنين ما اتصال را بصورت برعكس نيز برقرار كرده ايم كه زماني مقدار زاويه در CannonField تغيير كند مقدار LCDRange نيز بروزرساني مي شود. در مثال ما هرگز مستقيماً زاويه را تغيير نمي دهيم. ولي با برقراري آخرين ارتباط توسط connect( ) مطمئن مي شويم كه تغييرات آينده خللي در همزماني دو مقدار ايجاد نمي كند. اين موضوع قدرت برنامه نويسي مؤلفه و بسته بندي صحيح را شرح مي دهد. توجه كنيد كه چقدر مهم است كه سيگنال angleChanged( ) تنها زماني كه زاويه واقعاً تغيير مي كند منتشر گردد. اگر هردوي LCDRange و CannonField باهم اين وضعيت را منتشر كده باشند، برنامه بمحض اينكه يكي از مقادير تغيير كند وارد يك حلقه نامتنهاهي مي شود. [ltr] کد : QGridLayout *grid = new QGridLayout ( this , 2 , 2 , 10 ); // 2x2 , 10 pixel border تاكنون ما از اشيائي از QVBox و QGrid كه به مجموعه و گروه نياز نداشته اند براي مديريت geometry استفاده كرده ايم. اكنون، بنابراين، مي خواهيم كه مقدار بيشتري بر روي طرح كنترل داشته باشيم، و به كلاس قدرتمندتري بنام QGridLayout سوئيچ مي كنيم. QGridLayout يك شيء نيست، كلاسي متفاوت است كه مي تواند فرزندي از هر شيء را مديريت كند. به عنوان توضيح، ما آرايه اي 2*2 با حاشيه 10 پيكسل ايجاد كرده ايم. ( سازندة QGridLayout مي تواند كمي مرموز باشد، همچنين براي قراردادن اينگونه توضيحات خوب است) [ltr] کد : grid -> addWidget ( quit , 0 , 0 ); ما دكمه Quit را در قسمت بالا و چپ صفحه اضافه مي كنيم : 0.0 . [ltr] کد : grid -> addWidget ( angle , 1 , 0 , Qt::AlignTop ); زاويه LCDRange را در قسمت پايين و چپ قرار مي دهيم، تنظيم شده نسبت به خانه بالايي خود. ( همترازي يكي از چيزهايي است كه QGridLayout اجازه استفاده از آنرا مي دهد ولي QGrid اين كار را نمي كند.) [ltr] کد : grid -> addWidget ( cannonField , 1 , 1 ); شيء CannonField را در قسمت پايين و راست قرار مي دهيم. ( خانه بالا و چپ خاليست). [ltr] کد : grid -> setColStretch ( 1 , 10 ); ما به QGridLayout مي گوييم كه ستون سمت راست ( ستون 1) بسط يافتني است. چون ستون سمت چپ بسط يافتني نيست، QGridLayout سعي خواهد كرد كه اندازه اشياء سمت چپ تغيير نكند و تنها اندازه CannonField وقتي كه اندازه MyWidget تغيير مي كند، تغيير كند. [ltr] کد : angle -> setValue ( 60 ); ما مقدار زاويه اوليه را تنظيم مي كنيم. توجه كنيد كه ارتباط بين LCDRange و CannonField را برخواهد انگيخت. [ltr] کد : angle -> setFocus ( ); آخرين عمل ما تنظيم تمركز صفحه كليد روي زاويه است بنابراين ورودي صفحه كليد بصورت پيش فرض به شيء LCDRange فرستاده مي شود. LCDRange شامل هيچگونه KeyPressEvent( ) نمي باشد، بنابراين بنظر خواهد رسيد خيلي مفيد نباشد. بنابراين ،به سازنده اش خطي جديد اضافه مي شود : [ltr] کد : setFocusProxy ( slider ); LCDRange اسلايدر به عنوان نماينده تمركز (focus proxy) تنظيم مي كند. اين بدان معني است كه زماني كه كسي (برنامه يا كاربر) بخواهد تمركز صفحه كليد را به LCDRange بدهد، اسلايدر آنرا دريافت مي كند. QSlider يك رابط محبوب صفحه كليد دارد، بنابراين تنها با يك خط كد نويسي يك رابط همانند آنرا به LCDRange داده ايم. عملكرد برنامه: حالا صفحه كليد كارهايي انجام مي دهد ـ كليدهاي جهت دار، Home، End، PageUp، و PageDown همه كارهاي قابل درك را انجام مي دهند. وقتي كه روي اسلايدر كاري انجام شد، CannonField مقدار جديد زاويه را نشان مي دهد. بمحض تغيير اندازه، CannonField تاحد ممكن فاضاي بيشتري را مي گيرد. تمرينات : سعي كنيد اندازه پنجره را تغيير دهيد. اگر شما آنرا واقعاً تنگ و يا واقعاً گشاد كنيد چه اتفاقي مي افتند؟ اگر شما همترازي از بالا (AlignTop) را حذف كنيد، چه اتفاقي براي مكان و اندازهLCDRange مي افتد؟ چرا؟ اگر شما قابليت بسط يافتن را به ستون سمت چپ بدهيد، وقتي كه شما اندازه پنجره را تفيير مي دهيد چه اتفاقي مي افتد؟ از setFocus( ) صرفنظر كنيد. كدام رفتار را ترجيح مي دهيد؟ سعي كنيد “Quit” را در فراخواني QButton:etText( ) به “&Quit” تغيير دهيد. چهره دكمه چه تغييري مي كند؟ چه اتفاقي مي افتد اگر در هنگام اجراي برنامه شما كليد Alt+Q را بزنيد؟ (در بعضي صفحه كليدها بصورت Meta+Q است) متن درون CannonField را به وسط آن هدايت كنيد. حالا شما براي فصل نهم آماده هستيد. |
|||
2011-04-18, 09:18 AM,
ارسال : #2
|
|||
|
|||
Re: آموزش توابع Qt قسمت هشتم
xigmacorporation نویسنده :فصل هشتم : Preparing for Battle |
|||
2011-04-18, 09:19 PM,
ارسال : #3
|
|||
|
|||
پاسخ: Re: آموزش توابع Qt قسمت هشتم
آقا دست شما درد نکنه، من با pyqt قبلا یه مقدار کار کرده بودم. فقط خواستم قدردانی کنم ازتون.
Lenovo Thinkpad R61 , Arch 64Bit kernel 3.7, kde 4.10, chromium 25 <!-- m --><a class="postlink" href="http://ebrahimraeyat.blogfa.com/">http://ebrahimraeyat.blogfa.com/</a><!-- m --> |
|||
|