تحدثنا في المقال السابق عن حاوية العنوان label و صناديق المدخلات Entry والتي هي جزء من عناصر الواجهة الرسومية Widgets في مكتبة TKinter، وسنواصل الحديث في هذا المقال عن مجموعة العناصر التي يمكننا إضافتها للنافذة الرئيسية في واجهات المستخدم الرسومية وهي الأزرار Buttons ومربعات الرسائل messagebox بقليل من التفصيل.
هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة:
- واجهات المستخدم الرسومية في بايثون باستخدام TKinter.
- مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون.
- حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون.
- الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون.
- مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون.
الأزرار Buttons
تعد الأزرار واحدة من أهم العناصر لواجهات المستخدم الرسومية، وهي عبارة عن مربعات قابلة للنقر عليها، حيث أن الغرض الرئيسي منها تفاعل الواجهة الرسومية مع نقر المستخدم على الأزرار لتنفيذ أمر معين مربوط بها.
إنشاء الأزرار داخل النافذة
نختار اسم المتغير المطلوب ليمثل الأزرار ويُستخدم الصنف Button من مكتبة Tkinter لذلك، ويعطى أولًا المكان الذي نريد وضع الزرار فيه وهو النافذة الرئيسية، ومن ثم النص المراد عرضه داخله ليوضح الهدف منه أو العمل الذي سيقوم بتنفيذه عند النقر عليه باستخدام الخاصية text على النحو التالي:
First_button=Button(main_window,text="النص")
تنشئ الشيفرة التالية زرارًا يعرض كلمة "موافق" ومن ثم تضعه على النافذة الرئيسية باستخدام الدالة pack
:
from tkinter import * main_window = Tk() main_window.title(" الأزرار ") First_button=Button(main_window,text='موافق') First_button.pack() main_window.mainloop()
نحصل بتشغيل الشيفرة على الشكل التالي:
نافذة بزر
خصائص الأزرار
يمكننا تغيير الكثير من خصائص الأزرار كتغيير لون النص fg
، ولون الخلفية bg
، ونوع الخط font
، ولون الأزرار أثناء النقر عليها activebackground
، ولون النص أثناء النقر عليه activeforeground
، وسمك الحدود bd
، بالإضافة إلى ذلك تسمح الخاصية relief
بتعديل نوع الحدود حيث يمكن إعطائها قيم مختلفة مثل :
raised, flat, ridge, groove and sunken.
كذلك يمكننا التحكم بحالة الزر باستخدام الخاصية state
حيث يكون فعالًا normal
افتراضيًا ويمكننا تغييره إلى غير فعال disable
، ويمكننا عمل ذلك إما أثناء إنشاء الزر أو في خطوة لاحقة مستقلة باستخدام الدالة config
على النحو التالي:
First_button.config(state='disable')
كما يمكننا التعديل على الخصائص باستخدام مبدأ القواميس dictionary
حيث نقوم بمعاملة العنصر كقاموس ونستخدم اسم الخاصية المراد وضع قيمة لها كمفتاح للقاموس ونضع القيمة المرغوبة على النحو التالي:
First_button['state']='disable'
سنقوم برسم زر بالخصائص التالية لون النص fg
أبيض، ولون الخلفية bg
أخضر، وبخط من نوع Verdana
بحجم 14 ويكون النص "موافق" تحته خط، بحدود ثخينة bd
بمقدار 5 ونوع حدود relief
بقيمة groove
ونحيطه بمساحة حدود داخلية وخارجية على النحو التالي:
from tkinter import * main_window = Tk() main_window.title(" الأزرار ") First_button=Button(main_window,text='موافق', font = "Verdana 14 underline", fg="white", bg="green", bd=5 ,relief ='groove') First_button.pack(padx=10,pady=30,ipadx=20,ipady=20) main_window.mainloop()
عند تشغيل الشفرة سنحصل على الشكل التالي:
نافذة بزر ملون
استجابة الأزرار
عند النقر على زر موافق في النافذة السابقة لا يحصل شيء، وذلك لأننا لم نقم بتحديد العمل المطلوب تنفيذه عند النقر على الزرار، ونحتاج لضبط ذلك أن نكتب دالة نضع بداخلها الشفرة المراد تشغيلها عند النقر على الزرار ونربطها معه باستخدام الخاصية command
على النحو التالي:
First_button=Button(main_window,text="النص" , command=function_name)
حيث تمثل function_name
اسم الدالة التي سنكتبها، وسنعيد كتابة الشفرة السابقة ونضع استجابة للزر بحيث تظهر لنا رسالة ترحيبية عند النقر عليه في حاوية العنوان، لذا سنقوم بتعريف دالة نسميها CallBack
ونضع فيها شفرة إظهار رسالة التعريف على النحو التالي:
from tkinter import * main_window = Tk() main_window.title(" الأزرار ") def callback(): mylabeltext.set(" مرحباً باستجابة الأزرار ") First_button=Button(main_window,text='موافق', font = "Verdana 14 underline", fg="white", bg="green", bd=5 ,relief ='groove', command=callback) First_button.pack(padx=10,pady=30,ipadx=20,ipady=20) mylabeltext= StringVar() result_Label = Label(main_window, textvariable=mylabeltext ) result_Label.pack() main_window.mainloop()
وسنحصل على النتيجة التالية عند تشغيل الشفرة:
نافذة بزر يستجيب للنقر
إدراج صورة داخل زر
بإمكاننا استبدال النص الذي يُعرض بالزرار بصورة قد تكون أكثر تعبيرًا من الكلمات لفعل ذلك نحتاج إلى تعريف كائن من الصنف PhotoImage
وسنقوم بتسميته buttonphoto
، باستخدام الخاصية file
إذ سنعطيه مسار الصورة (مكان تواجدها في الجهاز) على النحو التالي:
buttonphoto = PhotoImage(file='Photo\path')
ومن ثم نستخدم الخاصية image
أثناء تعريف الزر ونسند لها قيمة الكائن الذي أنشأناه ستكون الشفرة كاملة على النحو التالي:
from tkinter import * main_window = Tk() main_window.title(" الأزرار ") def callback(): mylabeltext.set(" مرحباً باستجابة الأزرار ") buttonphoto = PhotoImage(file='Arrow.png') First_button=Button(main_window,image=buttonphoto, bd=5,command=callback) First_button.pack(padx=10,pady=30,ipadx=20,ipady=20) mylabeltext= StringVar() result_Label = Label(main_window, textvariable=mylabeltext ) result_Label.pack() main_window.mainloop()
وسنحصل على النتيجة التالية:
نافذة بزرار على شكل صورة
استخدمنا في المثال السابق الصورة المسماة Arrow.png وكانت موجودة في نفس مسار وجود ملف الشفرة، لذلك وضعنا اسمها مباشرة، ولو كانت في مكان مختلف لقمنا بتحديد مكان وجودها، للأسف الكائن PhotoImage
يدعم فقط صيغ محدودة وهي:
GIF, PGM, PPM, PNG
ولو أردنا أن نعرض نصًا وصورة في نفس الزرار يجب علينا أن نستعين بالخاصية compound
والتي تحدد مكان ظهور الصورة بالنسبة للنص وتأخذ قيمة من الاحتمالات التالية:
'top','bottom', 'left', 'right', 'center','none'
يعرض السطر التالي الصورة فوق النص:
buttonphoto = PhotoImage(file='Arrow.png') First_button=Button(main_window,image=buttonphoto ,text='موافق', bd=5 ,command=callback ,compound='top')
وتكون النافذة بالشكل التالي:
نافذة بزرار صورة ونص
مربع الرسائل messagebox
يحتاج البرنامج عند تطوير تطبيقات واجهات المستخدم الرسومية بالغالب لإعلام المستخدم بسير الأحداث، وإخباره برسائل الخطأ أو الرسائل التحذيرية ونحوها، على سبيل المثال عند نقر المستخدم على زر الحفظ، من الجيد إظهار رسالة تبين حالة العملية من نجاح أو فشل. أو عند حدوث خطأ ما وعدم تمكن البرنامج من إتمام مهمة معينة يُفترض إظهار رسالة تبين الخطأ ونوعه للمستخدم، لنتمكن من عمل هذا سنستعين بالوحدة messagebox من مكتبة Tkinter.
استدعاء مربع الرسائل
تأتي الوحدة messagebox
مدمجةً مع مكتبة Tkinter لذلك لا حاجة لأي تثبيت إضافي له، فقط يضاف أمر استدعاء في بداية الشفرة لنتمكن من استخدامها على النحو التالي:
from tkinter import messagebox
مربعات الرسائل الخبرية
النوع الأول من أنواع مربعات الرسائل هي الخبرية والتي تظهر رسالة للمستخدم مع زر واحد فقط تغلق النافذة بالضغط عليه. وسنتعرف إلى الدوال التالية التي تظهر رسالة خبرية للمستخدم:
-
showinfo
: تظهر مربع رسالة على شكل معلومة خبرية، لإخبار المستخدم بانتهاء تنفيذ أمر معين مثلًا -
showerror
: تظهر مربع رسالة على شكل رسالة خطأ، لإخبار المستخدم بحدوث خطأ أثناء تنفيذ أمر معين مثلًا. -
showwarrning
: تظهر مربع رسالة على شكل رسالة تحذيرية، لإخبار المستخدم بانتهاء تنفيذ أمر معين لكن بوجود أمر لم يتم بالشكل المطلوب مثلًا.
تأخذ جميع هذه الأنواع من المستخدم أمرين: أولًا عنوان مربع الرسالة وثانيًا نص الرسالة
showinfo(title, message) showerror(title, message) showwarrning(title, message)
عندما نرغب باستخدام واحدة من مربعات الرسائل السابقة نقوم باستدعائها مستخدمين اسم الوحدة على النحو التالي:
messagebox.showerror( title='Error', message='This is an error message.'))
يمكننا للكتابة بطريقة مختصرة تعديل سطر الاستدعاء منذ البداية ليكون على النحو التالي:
from tkinter.messagebox import *
ثم يمكننا استدعاء مربع الرسالة المطلوب باستخدام اسمه مباشرة دون الحاجة لوضع اسم الوحدة قبله.
سنقوم بعمل نافذة تحتوي ثلاث أزرار يقوم كل واحد منها بإظهار نوع من مربعات الرسائل عند النقر عليه، من خلال الشفرة التالية:
from tkinter import * from tkinter.messagebox import * main_window = Tk() main_window.title(" الأزرار ") def error_message(): showerror( title='خطأ',message='هذه رسالة خطأ') def info_message(): showinfo(title='معلومة',message='هذه رسالة معلومات') def warning_message(): showwarning(title='تحذير',message='هذه رسالة تحذيرية') Error_button=Button(main_window,bd=3,text='إظهار مربع رسالة خطأ ',command =error_message) Error_button.pack(ipadx=20,ipady=20) Info_button=Button(main_window,bd=3,text='إظهار مربع رسالة إخبارية',command =info_message) Info_button.pack(ipadx=20,ipady=20) warning_button=Button(main_window,bd=3, text='إظهار مربع رسالة تحذيرية',command=warning_message) warning_button.pack(ipadx=20,ipady=20) main_window.mainloop()
وسنحصل على النافذة التالية:
نافذة بأزرار لعرض مربعات الرسائل
مربعات الرسائل
مربعات الرسائل الحوارية
النوع الثاني من أنواع مربعات الرسائل هي الحوارية والتي تُظهر للمستخدم رسالة وتنتظر منه استجابة وتأتي على عدة أشكال:
-
askquestion
: تظهر له خيار إما نعم أو لا Yes/No وترجع الدالة قيمة الزر الذي تم النقر عليه بصيغة Yes/No. -
askyesno
: تظهر له خيار إما نعم أو لا Yes/No وترجع الدالة قيمة الزرار الذي تم النقر عليه بصيغة True/False. -
askyesnocancel
: تظهر له خيار إما نعم أو لا أو إلغاء Yes/No/ Cancel وترجع الدالة قيمة الزر الذي تم النقر عليه بصيغة True/False/None على التوالي. -
askokcancel
: تظهر له خيار إما نعم أو إلغاء OK/ Cancel وترجع الدالة قيمة الزر الذي تم النقر عليه بصيغة True/False. -
askretrycancel
: تظهر له خيار إما إعادة المحاولة أو إلغاء retry/ Cancel وترجع الدالة قيمة الزر الذي تم النقر عليه بصيغة True/False.
تطبيق الآلة الحاسبة (الجزء الرابع)
بعد أن تعرفنا على عنصر الأزرار نستطيع الآن إكمال تطبيقنا ونضعها بداخل الإطار السفلي للآلة، نذكّر بالشكل التالي التخيلي للآلة الذي بدأنا منه فكرة ترتيب العناصر:
واجهة الآلة الحاسبة
رسمنا في الدروس السابقة الإطار العلوي وبداخله حاوية العنوان وصندوق المدخلات، وكذلك رسمنا الإطار السفلي ووصلنا إلى شكل التالي:
واجهة الآلة الحاسبة الثانية
سنبدأ الآن بوضع الأزرار من الشكل التخيلي نرى أن هناك شكل شبيه بالشبكة بأربعة أعمدة وخمسة صفوف، كما يوجد نوعين من الأزرار واحدة للأرقام، وواحدة للعمليات الحسابية، وتشترك جميع أزرار الأرقام بخصائص متشابهة فهي بطول 3 وعرض 10 ولون خلفية من درجات الأزرق مشابه لما استخدمناه في حاوية العنوان ولون نص أبيض، وأزرار العمليات تشابهها في الطول والعرض وتختلف عنها في لون الخلفية فهو رمادي و لون الخط أسود ويشتركون جميعًا بتغير شكل المؤشر عند المرور عليها ليصبح شكله كاليد.
بدلًا من أن نعيد كتابة الخصائص وتكرارها لكل زرار نستطيع إنشاء قاموس يحتوي على كل خاصية وقيمتها المطلوبة للأزرار المتشابهه ونستخدمه وقت الإنشاء، فنضع قاموسًا لأزرار العمليات سنسميه operators
وقاموسًا للأرقام سنسميه numbers
على النحو التالي:
numbers={'fg':"white",'width':10,'height':3,'bd':2,'bg':"#007CFF", 'cursor':"hand2"} operators={'fg': "black","width": 10,"height":3,"bd": 2, "bg":"#eee","cursor":"hand2"}
طبعًا لإنشاء الأزرار، سبق وذكرنا خلال الدرس أننا نحتاج لتكوين كائن من الصنف Button
ونحدد خصائصه عند إنشائه، لذا سننشئ على سبيل المثال الزر رقم 7 فتكون الشفرة باستخدام القاموس على النحو التالي:
seven = Button(btns_frame, text = "7",**numbers)
وسنراعي عند وضع الأزرار على الشبكة ترتيب أماكنها، فالزر رقم سبعة هنا سيكون في الصف الثاني الذي يحمل الرقم 1 (لأن الترتيب يبدأ من صفر) والعمود الأول الذي يحمل الرقم 0، على النحو التالي:
seven.grid(row = 1, column = 0)
وهكذا نقوم بوضع جميع الأزرار على الشبكة، من خلال الشكل نرى الزر الذي يحمل الحرف (C) وهو لمحو شاشة الإدخال والزر الذي يحمل الرقم 0 مختلفين قليلًا في الأبعاد عن بقية الأزرار الأخرى، فالرمز (C) يحجز مساحة ثلاثة أزرار والرقم صفر يحجز مساحة زرين، فنحتاج أن نكتب خصائصهما بشكل كامل بشكل منفصل عن البقية لأن فيهما اختلافًا عنهم في خاصية العرض، على النحو التالي:
clear = Button(btns_frame, text = "C", fg = "black", width = 32, height = 3, bd = 0, bg = "#eee", cursor = "hand2"( zero = Button(btns_frame, text = "0", fg = "white", width = 21, height = 3, bd = 2, bg = "#007CFF", cursor = "hand2")
وعند وضعهم على الشبكة نحتاج لاستخدام خاصية columnspan
والتي تحدد كم عدد الأعمدة التي سيشغلها هذا الزرار فتكون قيمتها عند الرمز (C) القيمة 3 وقيمتها عند الصفر 2 بالشكل التالي:
clear.grid(row = 0, column = 0, columnspan = 3) zero.grid(row = 4, column = 0, columnspan = 2)
يتبقى لنا الآن كتابة شفرات الدوال التي تتعامل مع الأزرار عند النقر عليها، فنحتاج لثلاثة دوال الأولى لتمسح محتوى صندوق الإدخال عند النقر على الرمز (C) وسنعطيها اسم bt_clear والثانية لتضيف محتوى الأزرار (الرقم أو العملية) على مربع الإدخال سنسميها btn_click
، ونربط كل زرار بالدالة المناسبة باستخدام الأمر command
وسنأخذ مثالًا على الزر رقم 4:
four = Button(btns_frame, text = "4",**numbers,command = lambda: btn_click(4))
ونكمل على هذا المنوال مع بقية الأزرار.
أما الدالة الثالثة مرتبطة بالنقر على علامة المساواة = سنسميها bt_equal
وهي تقوم بتنفيذ العملية الحسابية التي أدخلها المستخدم وتعرض النتيجة في مربع الإدخال، وسنضيف لها جزءًا بسيطًا في حال كانت العملية المدخلة خاطئة، فنستخدم مربعات الرسائل لنُظهر رسالة خطأ عند عدم القدرة على تنفيذ العملية المدخلة:
showerror( title='خطأ',message='العملية الحسابية غير صحيحة')
الكود بالكامل سيكون على النحو التالي:
from tkinter import * from tkinter.messagebox import * from ctypes import windll windll.shcore.SetProcessDpiAwareness(1) mycalculator = Tk() mycalculator.title("آلة حاسبة بسيطة") mycalculator.geometry("575x740") mycalculator.resizable(0, 0) input_frame = LabelFrame(mycalculator,text="المدخلات ",bd=3,width=550) input_frame.pack(side=TOP) btns_frame = LabelFrame(mycalculator,text=" لوحة الأرقام والعمليات ", bg="white",width=550,bd=3) btns_frame.pack() expression = "" input_text = StringVar() def bt_clear(): global expression expression = "" input_text.set("") def btn_click(item): global expression expression = expression + str(item) input_text.set(expression) def bt_equal(): try: global expression result = str(eval(expression)) input_text.set(result) expression = "" except Exception : showerror( title='خطأ',message='العملية الحسابية غير صحيحة') input_label=Label(input_frame,text="أدخل المعادلة الحسابية ",bg="#007CFF",fg="white") input_label.grid(row=0, column=1,ipady=10) input_field = Entry(input_frame, width=18, font=('arial', 12, 'bold'),textvariable=input_text) input_field.grid(row=0, column=0,ipady=10) numbers = {'fg':"white",'width':10,'height':3,'bd':2,'bg':"#007CFF",'cursor':"hand2"} operators={'fg': "black","width": 10,"height":3,"bd": 2, "bg":"#eee","cursor":"hand2"} #السطر الأول clear = Button(btns_frame, text = "C",fg = "black", width = 32, height = 3, bd = 2, bg = "#eee", cursor = "hand2",command =bt_clear) clear.grid(row = 0, column = 0,columnspan = 3) divide = Button(btns_frame, text = " / ", **operators,command = lambda: btn_click("/")) divide.grid(row = 0, column = 3) ###السطر الثاني seven = Button(btns_frame, text = "7",**numbers,command = lambda: btn_click(7)) seven.grid(row = 1, column = 0) eight = Button(btns_frame, text = "8",**numbers,command = lambda: btn_click(8)) eight.grid(row = 1, column = 1) nine = Button(btns_frame, text = "9",**numbers,command = lambda: btn_click(9)) nine.grid(row = 1, column = 2,) multiply = Button(btns_frame, text = " * ", **operators,command = lambda: btn_click("*")) multiply.grid(row = 1, column = 3) #السطر الثالث four = Button(btns_frame, text = "4",**numbers,command = lambda: btn_click(4)) four.grid(row = 2, column = 0) five = Button(btns_frame, text = "5",**numbers,command = lambda: btn_click(5)) five.grid(row = 2, column = 1) six = Button(btns_frame, text = "6",**numbers,command = lambda: btn_click(6)) six.grid(row = 2, column = 2) minus = Button(btns_frame, text = "-",**operators,command = lambda: btn_click("-")) minus.grid(row = 2, column = 3) #السطر الرابع one = Button(btns_frame, text = "1",**numbers, command = lambda: btn_click(1)) one.grid(row = 3, column = 0) two = Button(btns_frame, text = "2", **numbers ,command = lambda: btn_click(2)) two.grid(row = 3, column = 1) three = Button(btns_frame, text = "3", **numbers , command = lambda: btn_click(3)) three.grid(row = 3, column = 2) plus = Button(btns_frame, text = "+",**operators,command = lambda: btn_click("+")) plus.grid(row = 3, column = 3) #السطر الخامس zero = Button(btns_frame, text = "0", fg = "white", width = 21, height = 3, bd = 2, bg = "#007CFF", cursor = "hand2", command = lambda: btn_click(0)) zero.grid(row = 4, column = 0, columnspan = 2) point = Button(btns_frame, text = ".",**numbers,command = lambda: btn_click(".")) point.grid(row = 4, column = 2) equals = Button(btns_frame, text = "=", **operators,command = lambda: bt_equal()) equals.grid(row = 4, column = 3) mycalculator.mainloop()
وبهذا نكون شبه أكملنا تطبيق الآلة، وسنضيف لها قائمة رئيسية لعرض معلومات عنها، وهذا ما سنتعرف عليه في الدرس القادم من هذه السلسلة.
المصادر
- Python - Tkinter Button.
- Tkinter Button.
- Tkinter messagebox.
- Python Tkinter messagebox – Displaying Prompts.
- Tkinter askyesno.
- Python - Tkinter grid() Method.
اقرأ أيضًا
- المقال التالي: مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون
- المقال السابق: حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون
- واجهات المستخدم الرسومية في بايثون باستخدام TKinter
- المرجع الشامل إلى تعلم لغة بايثون
- النسخة الكاملة من كتاب البرمجة بلغة بايثون
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.