מדריך: פיתוח יישומים גרפיים בפייתון עם Qt

29/10/2017

פוסט זה כולל טיפ קצר לעבודה יעילה עם Python. אם אתם רוצים ללמוד פייתון יותר לעומק אני ממליץ על קורס Python כאן באתר.
הקורס כולל עשרות שיעורי וידאו והמון תרגול מעשי וילמד אתכם Python בצורה מקצועית מההתחלה ועד הנושאים המתקדמים.

נו אז התחלתם ללמוד פייתון ועכשיו רוצים גם להראות לחברים כמה זה מדליק. הבעיה שתוכניות טקסט בלבד לא עושות רושם מי יודע מה. עם המדריך הבא תוכלו להתחיל לכתוב תוכניות פייתון שגם מציגות חלונות כמו אפליקציות אמיתיות.

1. מה צריך

נתחיל בהתקנות. ספריית Qt היא ספריה גרפית וותיקה התומכת בכל מערכות ההפעלה (חלונות, מק ולינוקס וגם אנדרואיד ו iOS). הספריה כתובה ב C++ ויש לה חיבור עם פייתון כך שאפשר להשתמש בה בצורה מלאה מתוך תוכנית פייתון.

נתחיל בהתקנת הספריה עצמה. הורידו את קובץ ההתקנה מהקישור המתאים:

למשתמשי חלונות http://mirrors.dotsrc.org/qtproject/official_releases/qt/5.9/5.9.2/qt-opensource-windows-x86-5.9.2.exe

למשתמשי מק http://mirrors.dotsrc.org/qtproject/official_releases/qt/5.9/5.9.2/qt-opensource-mac-x64-5.9.2.dmg

ולאחר מכן התקינו באמצעות הפעלת הקובץ שהורדתם.

בשלב שני יש להתקין את הספריה PyQt5 שהיא ספריית Python המתחברת עם Qt. מי שעובד משורת הפקודה יכול לכתוב:

pip3 install PyQt5

אלה מכם שעובדים עם PyCharm נכנסים לתפריט File->Settings ושם בוחרים ב Project Interpreter ולחוצים על הפלוס הקטן כפי שמופיע בתמונה כאן:

Project Interpreter Settings

לאחר מכן בוחרים מהרשימה את PyQt5 ולוחצים Install.

2. תוכנית פייתון גרפית ראשונה שלי

לאחר ההתקנה נבדוק שהכל עבד כמו שצריך. הקלידו את התוכנית הבאה והריצו:

from PyQt5.QtWidgets import *
import sys

app = QApplication(sys.argv)

lbl = QLabel("Hello World")
lbl.setStyleSheet("""
    font-size: 48px;
    text-align: center;
    background-color: #44FFD1;
    color: #360A14;
    padding: 50px;
""")
lbl.show()

app.exec_()

אם הכל הלך כשורה לאחר ההרצה תקבלו את הטקסט Hello World מופיע בחלון גרפי במרכז המסך.

עיצוב התיבה נכתב כרצף של מאפיינים במחרוזת טקסט מרובת שורות שמזכירה מאוד CSS. יש בתיעוד רשימה מלאה של המאפיינים שאפשר להשתמש בהם. לתוכניות פשוטות אני חושב שמה שהופיע כאן יספיק.

3. שיפור הממשק באמצעות Layout Managers

הדרך של Qt לסדר רכיבים גרפיים על המסך נקראת Layout Managers, או בעברית נכנה אותם מנהלי מיקום. כל מנהל מיקום מסדר רכיבים גרפיים לפי חוקיות מסוימת - למשל מנהל המיקום QHBoxLayout מסדר את הרכיבים בשורה אופקית. אפשר לשלב מספר מנהלי מיקום על המסך וכך לבנות ממשקים יחסית מורכבים.

בדוגמא הבאה ניקח את מנהל המיקום QGridLayout ונבנה בעזרתו ממשק פשוט הכולל תיבת עריכת טקסט ושני כפתורים לשמירת הטקסט לקובץ וטעינת הטקסט מקובץ. זה קוד התוכנית, ותצטרכו להקליד אותו במחשב כדי לראות איך זה נראה:

from PyQt5.QtWidgets import *
import sys

app = QApplication(sys.argv)

w = QWidget()
layout = QGridLayout(w)

btn_save = QPushButton("Save")
btn_load = QPushButton("Load")
textbox  = QTextEdit()

layout.addWidget(btn_save, 0, 0)
layout.addWidget(btn_load, 0, 1)
layout.addWidget(textbox, 1, 0, 2, 2)


w.show()
app.exec_()

4. חיבור כפתור בממשק לפעולות

האתגר הבא הוא חיבור פעולת משתמש לפעולה כך שקוד פייתון ייקרא בעקבות פעולה שמשתמש מבצע. ב Qt פעולת משתמש נקראת Signal ופונקציה שנקראת בתגובה לפעולה נקראת Slot. כדי שפעולת משתמש תביא להפעלת פונקציה עלינו לחבר את הפונקציה המתאימה לפעולה.

כך לדוגמא לכפתור יש Signal בשם clicked שמופעל בכל פעם שלוחצים על הכפתור. אם נחבר פונקציה לסיגנל זה היא תופעל כשמשתמש ילחץ על הכפתור.

ננסה את זה עם התוכנית הקודמת ונתחיל עם הודעת הדפסה. התוכנית הבאה מציגה את אותו ממשק של תיבת טקסט ומעליה שני כפתורים, אבל הפעם כשנלחץ על כפתור Save תופיע בתיבת הטקסט שורת טקסט חדשה שאומרת שלא ניתן לשמור את הקובץ. השורות שנוספו הן בסוף התוכנית מעל פקודת ה show:

from PyQt5.QtWidgets import *
import sys

app = QApplication(sys.argv)

w = QWidget()
layout = QGridLayout(w)

btn_save = QPushButton("Save")
btn_load = QPushButton("Load")
textbox  = QTextEdit()

layout.addWidget(btn_save, 0, 0)
layout.addWidget(btn_load, 0, 1)
layout.addWidget(textbox, 1, 0, 2, 2)

def write_text_into_textbox():
    textbox.append("Error Saving File...")

btn_save.clicked.connect(write_text_into_textbox)

w.show()
app.exec_()

כמובן שיהיה הרבה יותר מעניין אם התוכנית גם תתן למשתמש לבחור שם קובץ ותשמור את הטקסט לקובץ, או לחלופין בכפתור הטעינה תציג למשתמש דיאלוג בו ניתן יהיה לבחור קובץ ואז התוכנית תציג את תוכנו בתיבה. מסתבר ששינוי כזה די פשוט בזכות הפקדים הגרפיים המובנים ב Qt. הנה התוכנית המלאה שגם קוראת וכותבת לקבצים:

from PyQt5.QtWidgets import *
import sys
import fileinput

app = QApplication(sys.argv)

w = QWidget()
layout = QGridLayout(w)

btn_save = QPushButton("Save")
btn_load = QPushButton("Load")
textbox  = QTextEdit()

layout.addWidget(btn_save, 0, 0)
layout.addWidget(btn_load, 0, 1)
layout.addWidget(textbox, 1, 0, 2, 2)

def load_file():
    fname = QFileDialog.getOpenFileName(None, "Select File")[0]
    if len(fname) == 0: return

    for line in fileinput.input(fname):
        textbox.insertPlainText(line)

def save_file():
    fname = QFileDialog.getSaveFileName(None, "Select File")[0]
    if len(fname) == 0: return

    with open(fname, 'w') as f:
        f.write(textbox.toPlainText())

btn_save.clicked.connect(save_file)
btn_load.clicked.connect(load_file)

w.show()
app.exec_()

5. לאן עכשיו

פיתוח ממשקים גרפיים בפייתון ו Qt יעזור לכם לכתוב במהירות כלים שלאנשים יהיה כיף להשתמש בהם (וגם לעשות רושם טוב על חברים ומשפחה). יחד עם העובדה שקל להתאים את הממשקים ולהריץ אותם גם על טלפונים, זו מיומנות שכיף שיש לכם.

אבל Qt היא גם ספרייה מאוד גדולה ולא לומדים אותה ביום אחד, ובטח לא מקריאת מדריך או שניים. הקישורים הבאים יעזרו לכם להתקדם וללמוד יותר על הספריה:

  1. רשימת רכיבי Qt ותוכניות דוגמא שמשתמשות בהם: https://pythonspot.com/en/pyqt5/

  2. רשימה נוספת של תוכניות PyQt מוסברות (מסתיים בפיתוח מודרך של משחק טטריס): http://zetcode.com/gui/pyqt5/

כתבתם משהו מעניין ב PyQt ורוצים לשתף? שלחו או שימו קישור בתגובות.