استاندارد نویسی کد در PyQt

درود خدمت دوستان در این پست می خوام نکاتی را درباره استاندارد نویسی کد یادآوری بکنم اول باید اهمیت استاندارد را در کدها درک کنیم تا بتوانیم یک پروژه موفق رو کلید بزنیم در واقع رعایت نکردن استانداردها در کوتاه مدت و بلند مدت باعث مرگ و شکست یک پروژه می شود. در کوتاه مدت اثرش این هست که برنامه نویسان و گسترش دهندگان دیگر پروژه با عدم درک و فهم کد مواجه خواهند شد که باعث دل زدگی ، خستگی ، و اتلاف وقت شریکان و گسترش دهندگان برنامه یتان می شوید و اثر دراز مدتش هم به خود شخص شما بر می گرده که فرضا پروژه ای رو یک سال قبل انجام دادین اکنون برای استفاده مجدد و گسترش و بهینه سازی برنامتون به اون مراجعه می کنین ولی این بار با مشکل عدم فهم و درک کدی مواجه هستین که یکسال قبل شما خودتون همه کارشو رو انجام دادین . در زیر به چند قانون برای بهتر کردن کدهامون یادآوری می کنم که رعایت اونها الزامی است:

۱- برای انتخاب نام یک ایتم یا متغیر اگر نام انتخابی از چند واژه تشکیل شده باشد نخستین حرف هر واژه را با حروف بزرگ می نویسیم به هیچ صورت از فعل ها برای نامگذاری ایتم ها استفاده نکنین. فعل ها مانند: add,save,update,delete,…

۲- درنامگذاری ایتم ها در پایکیوت  نوع آیتم را هم ذکر کنین تا مشخص شود که شی مربوط به چه ویدجتی می باشد. برای مثال :

NameLabel = QLabel('name')
NameEdit = QLineEdit()

۳- برای نام گذاری توابع و متدها سعی کنین بجای استفاده از اسم از فعل استفاده کنین یعنی فعلی که تابع انجام می دهد مثلا فعل های save , delete, add, submit ,..  برای نام گذاری متدها سودمند هستن

۴- در هرجا از کد که لازم باشه از کامنت ها یا توضیحات برای یادداشت نکات و توضیحات کد استفاده کنین. این کار به خوانایی کد برای گسترش دهندگان دیگر و همچین برای خود شما که پس از مدت ها به سورس رجوع می کنین بسیار یاری رسان هستش.

۵- حتما  توو رفتگی ها و فاصله ی خطوط ، ظاهر شکیل کد رو حفظ کنین تا باعث خستگی و سردرگمی دیگران نشوید.

در پایان نکات بالا نه تنها برای فریمورک پایکیوت  بلکه برای هر برنامه ای با هر زبانی یک قانون نانوشته هستن که رعایت انها الزامی می باشد 🙂

 

 

 

48 دیدگاه برای «استاندارد نویسی کد در PyQt»

  1. سلام ایرج جان،
    ممنون به خاطر وقتی که میگذاری.
    این قطعه کد یعنی چی .
    من میخوام بدونم که چه زمانی از self و کی از ui.self و Widget.ui. استفاده میشه ,
    و این که در چه زمانی لازمه که تابع رو در کلاس جدید قرار بدم…>

    class CalculatorForm(QtGui.QWidget):
        def __init__(self, parent=None):
            super(CalculatorForm, self).__init__(parent)
    
            self.ui = Ui_CalculatorForm()
            self.ui.setupUi(self)
    
    
    

    با احترام
    سحر

    1. سلام. اگر ویدگت ها در خود کلاس تعریف شده باشند و بخوام از اون ویدگت در همون کلاس استفاده کنم از self استفاده می کنم.
      اگر که ویدجتها در کلاسی دیگه تعریف شده باشند اول باید اون کلاس رو اگر در فایل چدایی نوشته شده بوسیله ی import وارد کنم و بعدش از روی کلاس وارد شده یک شی یا ایتم یا ابجکت بسازم و از طریق اون ابجکت به ویدگت مورد نظر دسترسی پیدا کنم
      در مثال شما ما یک کلاسی داریم بنام Ui_CalculatorForm
      این کلاس احتمالا درون یه فایل دیگه تعریف شده. اون فایل رو بازش کن و ویدگتهای تعریف شده همراه نامشون رو ببین
      خب حالا ما می خوایم از این کلاس در برناممون استفاده کنیم اول یه شی بنام ui می سازیم

      self.ui = Ui_CalculatorForm()
      

      خب حالا اگر دوباره به کلاس Ui_CalculatorForm نگاهی بیاندازیم احتمالا چیزی شبیه زیر باید ببینیم

      class Ui_CalculatorForm(object):
          def setupUi(self, Form):
      

      که object به ما می گه این کلاس از نوع ابجکت هستش و والد یا پدر خاصی نداره که ویژگی های تعریف شده اون رو به ارث ببره. یعنی تمام ویدگت های تعریف شده در این کلاس مثل QLineEdit ها و QPushButton ها و QLabel ها… فعلا بدون استفاده هستن. برای اینکه بشه از این ویدگتها استفاده کرد نیاز داریم بجای object یک کلاس پدری قرار بگیره که تمام این ویدگتهارو در اختیار کلاس Ui_CalculatorForm قرار بده .
      پس نیاز به ایتم یا ابچکتهایی از نوع QDialog و QWidget یا QMainWindow داریم
      متد setupUi دقیقا همین کارو می کنه یعنی یک ابجکت پدر در اختیار شی self.ui می ذاره که این چا self هستش و self اشاره داره به کلاس CalculatorForm که فرزند QWidget هستش 🙂 خب بطور مفصل و دقیق همه چیزو توضیح دادم اگر مشکلی بود لطفا دوباره سوال کنین من در خدمتم

  2. ایرج جان، واقعا عالی بود, ممنونم.

    میخوام یک کلاس جدید و یک تابع در این کلاس بسازم.
    مشکل اینه که نمیدونم چطور این تابع رو صدا کنم.

    باز هم ممنون و با احترام
    سحر

    1. خواهش می کنم 🙂 اینم لینک ویرایش شده ی برنامتون:
      کد
      برای فراخوانی یه تابع توسط ویدگتها باید از سیگنالها استفاده کنیم هر ویدگتی سیگنالهای ویژه ی خودشو داره . لاین ادیت ها، پوش بوتونها ، تکست ادیتها و تیبل ها …
      در اینچا از سیگنال clicked برای پوش بوتن استفاده کردم:

      self.ui.pushButton.clicked.connect(self.sum_func)
      

      کد بالا به پایتون می گه وقتی روی ایتم pushButton کلیک شد به تایع sum_func کانکت شو و فراخوانی کن.
      برای اشنایی با سیگنالها به PyQt Class Reference در مستندات کیوتی رجوع کنید
      من برنامه رو ویرایش کردم و تغیراتی ایچاد کردم از جمله :

      if __name__ == '__main__':
          import sys
          app = QtGui.QApplication(sys.argv)
          window = sum_Form()
          window.show()
          sys.exit(app.exec_())
      
      
      
  3. گاهی اوقات کمک شاید کوچک از نظر خودمون تغییرات زیادی رو ایجاد کنه.
    ایرج جان, ممنونم

    شاد باشی
    با احترام سحر

    ps:
    من آلمان زندگی میکنم، اگر کمکی بخواهی با کمال میل سعی میکنم

  4. سلام ایرج عزیز،

    من باز هم سوال دارم، میبخشی بخدا کس دیگه‌ای نیست که کمک کنه.:)

    برنامه‌ای که فرستادم کار می‌کنه، و خروجی اون یک موج دیجیتال هست. می‌خوام این موج در فرم اصلی‌ توسط Matplotlib_Widjet بتونه نمایش داده شه , اما نمیدونم چطوری?? 🙂
    در واقع می‌خوام بدونم در PYQT چطور فرمان plot رو می‌شه صدا کرد

    ممنونم، با احترام سحر.

    1. درود سحر خانم. خواهش می کنم مشکلی نیست بازم سوالی بود بپرسین تونستم حتما کمک می کنم خوشحال می شم. من تا حالا با این ماژول ها کار نکرده بودم و راستش بار اولم بود دانلودشون کردم . برنامه رو نگاه کرذم و تغیراتی دادم که با کیوتی هماهنگ شه 🙂 و بخوبی کار می کنه . اینم لینک فایل ویرایش شده و اینم یه برنامه مشابه که بم کمک کرد تغییرات رو انجام بدم

  5. سلام ایرج جان،

    ممنون به خاطره جوابتون، منتها منظورم این بود
    ، مثلا:

    من یک فرم طرح کردم، وقتی‌ دکمه کلیک می‌شه، می‌خوام منحنی در مکان – Matplotlib Widjet – رسم شه نه روی فرم اتوماتیک(که انجام می‌شه )

    بسیار ممنونم و شاد باشید
    با احترام سحر

  6. سلام ایرج جان،

    میدونم که خوبی‌، من هم خوبم، و مثل همیشه باز هم ازتون کمک می‌خوام، و از قبل ممنونم.

    ۲ تا سوال دارم:

    ۱. چطور می‌شه یک برنامه ..PYQT4 را که به پایتن تبدیل شده و بهش تابع اضافه کردیم رو دوباره به محیط .PYQT4 برگردونیم و گسترش دهیم، مثلا چند تا دکمه اضافه شه یا …

    ۲. برنامه طراحی در محیط Matplotlib رو که برام لطف کردی و فرستادی، بهم جواب میده اما با کدهای برنامه نویسی در .PYQT4 . فرق داره، چرا و چطور می‌شه تغییرش داد.

    میبخشی :;
    شاد باشی‌

    با احترام سحر

    1. سلام 🙂 . فرمی رو که در دیزاینر کیوتی طراحی کردین و به پایتون تبدبل کردین دیگه نمیشه در دیزانر استفادش کرد. از همون اول که فرم رو طراحی می کنین سعی کنین کامل طراحیش کنین و اون وقت تبدیلش کنین و کار کنین.
      سوال دوم: من در اینجا برنامه کیوتی را با دیزانر ننوشتم بلکه بصورت دستی کد زدم تا فرم رو درست کردم . وقتی که یه فرم را بدون استفاده از دیزاینر کیوتی ایجاد می کنیم برای راحتی و سرعت کار خیلی از کدهایی که دیزاینر به فرم اضافه می کنه رو حذف می کنیم تا که فرممون شلوغ نشه. دیزاینر واقعا خیلی وقتا فقط الکی کد رو شلوغ می کنه و چیزهایی رو اضافه می کنه که مورد استفاده ما قرار نمی گیرن.
      وقتی بدون دیزاینر می خوایم فرم طراحی کنیم چارچوب اصلی کدمون با کمی تغیر چیزی شبیه زیر هستش :

      from PyQt4 import QtGui , QtCore
      
      class MainWindow(QtGui.QMainWindow):
          def __init__(self):
              super(MainWindow, self).__init__()
              # QMainWindow.__init__(self)
      
      
      
      if __name__ == '__main__':
          import sys
          app = QtGui.QApplication(sys.argv)
          window = MainWindow()
          window.show()
          sys.exit(app.exec_())
      
      1. سلام ایرج جان،

        خدا عمرت رو طولانی‌ کنه !!! از اون دعا هست که مادر بزرگها به نوه‌‌هاشون میگن.

        ممنونم به خاطره جوابت، استاد من یک عقیده‌ای داره که من فکر می‌کنم راست میگه، که: یک نرم افزار کارا حتما فایل هاش قابل گسترش هستند، مگر اینکه در.help صریحا ذکر شده باشه و می‌خواد این رو ثابت کنم که از اون حرفاست، شما آیا جائی‌ در help یا جای معتبر دیگه‌ای خوندی که قابل گسترش (تبدیل از py. به ui. نیست ) یا این که در طی‌ کار متوجه شدی؟ )

        قربانت سحر

        1. مرسی سحر خانم 😀
          من جایی نخوندم ولی ui کلا فایلی با محتو یات xml هستش که محتویات فرم رو توصیف می کنه مثلا توش ذکر شده که فلان ویدجت با چه خواصی (مثل طول و عرض و نام و موقعیتش در فرم ) در فرم قرار داره. وقتی دیزاینر ui رو باز می کنه از روی همین تگ ها دوباره فرم رو شبیه سازی می کنه. من برنامه های اپن سورس زیادی رو دیدم اگر برنامه با دیزانر طراحی شده باشه یعنی فایل ui داشته باشه ، این فایل ui رو در کنار منطق برنامه یا سورس برنامه که با py هستش ذخیره می کنن. اگر گسترش دهنده دیگه ای یا برنامه نویسی دیگه ای بخواد روی برنامه کار کنه و اصلاحش کنه می تونه از اون فایل ui استفاده کنه و تغیرات درونش بده اون وقت دوباره در پایتون بکار ببرش.
          راه دیگه هم این هست که ui رو به پایتون تبدیل نکنیم و مستقیما در پایتون واردش کنیم . اون وقت به راحتی هر تغیری توی ui بدین فوری قابلیت اجرا داره . اینجا آموزش بکار بردن مستقیم ui در پایتونه.
          پس اگر ui رو به پایتون تبدیل کنیم معمولا فایل ui رو کنار سورس نگه می داریم که اگه خواستیم تغیر بدیم ، با دیزاینر بازش کنیم تغیرات بدیم و دوباره به پایتون تبدیل کنیم .
          اما بیشتر از روش تبدیل ui به پایتون استفاده می شه

  7. اینم یه برنامه مشابه که بم کمک کرد تغییرات رو انجام بدم

    سلام ایرج جان،
    یک مدت از دست من راحت بودید، امتحان داشتم و سرم حسابی شلوغ بود.، تنها پروژه مونده که باید تا هفته آینده تحویل بدم .
    باز هم سوالت بی پایانم شروع شد. ممنونم به خاطر لطفتون . و امیدوارم وقت داشته باشی و مسافرت نباشی. 🙂

    با احترام سحر

    این برنامه رو شما برای من نوشتید. اما من چند سوال کلی روی اون دارم .
    من روال برنامه رو نوشتم :
    ۱- create Widgete 1 –> qwidgete
    –> create qLayout
    –> install layout manager for qLayout with parent:qwidgete
    –>create qscroll belongs to qlayout
    –> create ascrolling view onto qwidget –>qscroll

    ۲- create second Widget –> qscrollcontents
    –> qscrollcontents belongs to qwidgete
    –> create layout: qScrollLayout
    –> reparent qscrollcontents, parent is qscroll ????

    ۳- create a Child widgets–> qfigWidget
    parent is: qscrollContents
    –> create a figure–> fig
    –> create a canvas for render figure———???
    –>plot
    –>create a vertical layout –> plotLayout

    –> add the widget(canvas) into the plotLayout
    —–>install layout manager for plotLayout with parent: qfigWidget

    –> add qwidgete to it’s layout: qlayout
    —–> install layout manager for qScrollLayout with parent:qscrollcontents

    ۱- چرا ۳ تا ویجت ساختید و توی همون ویجت اولی رسم نکردید ؟
    ۲- ویجت دوم لزومش چیه؟؟

    ۳- برای این فرمان کلی توضیح پیدا کردم اما نمیفهمم دقیقا چیه و چرا در پایتون الزامی نیست.
    canvas = FigureCanvas(fig)

    ۴- چرا ویجت سوم را فرزند تعریف کردید، و چرا فرزند ویجت دوم نه اول?
    ۵- و این چرا این طور تعریف شده و همون اول والد رو تعریف نکردیم.
    qscrollContents = QtGui.QWidget(qscrol))

    ps1 : پسوردم رو فراموش کردم مجبور شدم یوزر جدید بسازم ، میبخشی
    ps2: قطعه برنامه ی که گذاشتم رو میشه لطفآ پاک کنید ، چون متعلق به پروژمه و پروژه ها خط به خط با اطلاعات موجود در اینترنت چک میشه ، بعد از تحویل، اطلاعات روبا افتخار به طور کامل میفرستم خدمتتون ( چه بخواهید یا نخواهید 🙂 )، ممنون

    1. سلام سحر خانم نه بابا خوشحالم کردین . ببین اون برنامه ای که به لینکش اشاره کردین یه برنامه ی اماده بود توی نت که بیشتر جنبه ی آموزشی داشت و کاربردی نبود یعنی تکه کدی نبود که بشه برای بکار گیری در یه پروژه روش حساب کرد من روش کار کردم هم جنبه اموزشی رو ساده تر کردم و هم کاربردی ترش کردم که واسه یه پروژه مناسب باشه و از اطلاعات خودتون پروژه ی خودتون براش استفاده کردم. برنامه خودمو توی لینک قبلیش گذاشتم حالا اگر نیاز بدونین اون رو هم واستون توضیح می دم 🙂


      http://fpaste.org/zkAz/
      برنامه ای که بالا گذاشتم با اهداف آموزشی شما مناسبتر جور میاد . دوباره نگاش کنین مشکلی بود بپرسین 🙂

  8. سلام ،
    باور نمیکردم که اینقدر خوش شانسم، ;))

    در واقع سوال کلی اینه که در چه صورت ترجیح میدیم از لایه های متعدد استفاده کنیم. و کلا این ترجیح در استفاده است یا اجبار در استفاده از لایه های متعدد?
    باز هم ممنون
    قربانت سحر

    1. 😀 . خب ببینین لایه ها برای چینش ویدجت ها کنار هم مورد استفاده قرار می گیرند . پس برای چینش افقی یا عمودی یا فرم مانند یا … بایه از اون لایه مخصوص استفاده کنیم . بعدا همه ی لایه هارو باهم درون یه لایه ی دیگه قرار می دیم تا یه لایه ی واحد داشته باشیم . بعدش اون لایه ی واحد روی یه ویدجت اصلی که پنجره رو ایجاد می کنه ست می کنم. حالا چجوری می فهمم که چجوری لایه ای رو باید بکار ببرم؟ خب توی ذهنم یه شکل از پنجره رو و محل قرار گرفتن ویدجت هارو تجسم می کنم و بعدش تصمیم می گیرم چه لایه ای رو بکار ببرم . 🙂 شما میخوای با دیزاینر برنامتون رو طراحی کنین؟ یا با کد نویسی دستی؟

      1. ایرج جان نگو ، که کلافه ام حسابی،
        من باید برنامه آموزشی بنویسم، که بچه های فوق که وقت ندآرند آموزش ببینن بر اساس اون چیزی که نوشتم هر فیلتری رو که میخوان به سادگی و بدون هر پیش زمینه ی بتونن طراحی کنن در واقع سیستم قدم به قدم. من این رو در پایتون نوشتم حالا باید در پایکویت هم بنویسم.
        بخاطره همین باید عمقی بفهمم که بتونم صحیح منتقل کنم.
        اصلا وقت هم ندارم،و……
        به خاطر جوابت ممنونم. شاد باشی

  9. ۳- برای این فرمان کلی توضیح پیدا کردم اما نمیفهمم دقیقا چیه و چرا در پایتون الزامی نیست.
    canvas = FigureCanvas(fig)

    ۴- چرا ویجت سوم را فرزند تعریف کردید، و چرا فرزند ویجت دوم نه اول?
    ۵- و این چرا این طور تعریف شده و همون اول والد رو تعریف نکردیم.
    qscrollContents = QtGui.QWidget(qscrol))

  10. ایرج جان،
    این self.retranslateUi(FirstMpl) چه مفهومی داره، توی پرانتزش چی مینویسیم , بعضی جاها دیدم که نوشته self ، یا نام فرم اصلی …

    این یکی از نتایج سرچ بود که مفهوم کلی رو نمیرسونه, منو شیر فهم نمیکنه ، اون پارانتزش …
    Automatcally connect signals to slots by their name. This is also
    done for you if you use the result of pyuic4, in the setupUi .

    قربانت

    1. retranslate ui
      این تابع همونجور که از نامش هم پیداس کار ترجمه هم زمان فرم رو برعهده داره. یعنی؟ مثلا ویدجت هایی که داخل فرم ui با حروف انگلیسی نام گذاری کردین می تونین اینجا به المانی یا فارسی ترجمه کنین و بمحض باز شدن پنجحره مثلا دکمه ها رو با نوشته های فارسی یا المانی دید همینجور برای تکست ها و لیبل ها .
      حالا درون پرانتزش چی باید بذاریم؟ خب فکر کنم هم می شه ؟ اسم فرم اصلی رو. اسمی که در تابع setupUi بعنوان آرگومان دوم داده شده یعنی Form

          def setupUi(self, Form):
      
    1. connectSlotsByName
      یه جستجوی بازگشتی رو برای تمام اشیای فرزند شی داده شده (در اینجا FirstMpl ) انجام می ده و سیگنال های اشیا رو به اسلات های شی متصل می کنه 🙂

  11. معمولا از این توابع وقتی استفاده می شه که با دیزانر فرم رو طراحی کردین و به پایتون تبدیل می کنین اما اگر بصورت دستی بخوایم فرم رو طراحی کنیم معمولا این توابع زیاد کاربردی ندارن

  12. http://doc.coin3d.org/SoQt/classSoQtComponent.html

    سلام ایرج جان،
    یک دیاگرام عالی دیدم اما نمیدونم آیا برای پایکویت هم روال همینه ( یعنی من این رو بنویسم درسته ؟ )، یک سایت میشناسی که برای پایکویت این طوری توضیح داده باشه
    قربان یو سحر

    توضیحاتت عالی بود ممنون

    1. بله . فکر کنم ویدجت های خاصی هستن یا ویدجت های معمولیای که بشون ویژگی های جدیده اضافه شده باشه و بشه توی دیزاینر ازشون استفاده کرد. توی مثال های کیوتی که توی ویندوز نصبه نمونه کامپونت هایی برای دیزانیر هست که با پایتون ساخته شدن 🙂 راستی یه سری به سایت زد کد بزنین کیوتی رو جالب توضیح داده.
      http://www.zetcode.com/tutorials/pyqt4/

  13. سلام آقا ایرج….
    اگه زحمتی نیست لینک دانلود یه کتاب الکترونیکی آموزش پایتون کیوتی رو بزار. یه کتاب هفتاد صفحه ای رو خودم دارم و خوندم. کتاب rapid introduction to PyQt …. رو هم تا صفحه ۲۰۰ خوندم، نحوه توضیحات مطالبش خیلی مزخرف و وقتگیر بود گذاشتمش کنار…
    اگه کتاب دیگه ای داری لطفا ایمیل بزن لطفا …
    مال ئاوا
    یا حق

  14. سلام ایرج جان ،
    شما کتاب دعای من هستید، من هم مدام دست به کتاب .
    وقتی میگم create an instance منظور چیه؟
    و ممکنه لطفآ یک تعریف صد در صد دقیق در مورد این به من بنویسید.

    class window():
        def __init__(self, parent=None):
            QtGui.QWidget.__init__(self,parent)
            self.ui = Ui_Dialog()
            self.ui.setupUi(self)
    
    
    

    ممنونم
    سحر

    1. create a instance
      instqance همان شی یا ابجکت هستش .

      class k:
        pass
      
      a = k()
      

      در بالا a یک نمونه یا ابجکت یا شی ساخته شده از کلاس کا می باشد.

      class window():
          def __init__(self, parent=None):
              QtGui.QWidget.__init__(self,parent)
              self.ui = Ui_Dialog()
              self.ui.setupUi(self)
      

      parent اشاره به والد یا پدر پنجره داره. حتما برنامه هایی رو دیدین که وقتی پنجره ی اصلی بسته شد تمام پنجره های فرعی نیز بسته می شن . پرنت در اینجا none هست یعنی پدری نداره .

      QtGui.QWidget.__init__(self,parent)
      این خط برای وراثت کلاس برناممون مورد استفاده قرار می گیره و به کلاس window ویژگی ها و خصوصیات کلاس پدر یعنی QtGui.QWidget رو می بخشه. و در کلاس window می توان از ویدجت های کلاس پدر استفاده کنیم . بعضی وقتا جای خط بالا از تابع سوپر هم استفاده می شه این دو معادل هستن فرقی ندارن.

      self.ui = Ui_Dialog()
      خط بالا هم همان فرم UI طراحی شده خودمون هست.
      self.ui.setupUi(self)
      self اشاره به کلاس window می کنه . window هم خصوصیات QtGui.Qwidget رو به ارث برده
      متد یک ابجکت پدر در اختیار شی self.ui می ذاره که این چا self هستش و self اشاره داره به کلاس window که فرزند QWidget هستش

  15. آقا جان میشه یه پستی درباره کلاس و تابع در پایتون بزاری و توضیح کاملی نسبت به اون بدی و اگه کتابی درباره این موضوع داری یا میشناسی معرفی کنی با تشکر البته فارسی باشه بهتره!!

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *