البحث في الموقع
المحتوى عن 'واجهات المستخدم الرسومية في بايثون'.
-
تحدثنا في المقال السابق عن حاوية العنوان 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 المرجع الشامل إلى تعلم لغة بايثون النسخة الكاملة من كتاب البرمجة بلغة بايثون
-
نستكمل في هذا المقال ما كنا قد بدأناه في سلسلة مقالات واجهات المستخدم الرسومية في بايثون باستخدام مكتبة TKinter، فبعد أن تحدثنا عن النافذة الرئيسية ومجموعة العناصر التي من الممكن أن نضعها عليها بشرح مجمل، سننتقل الآن إلى شرح تفصيلي عن العناصر وسنبدأ بشرح حاوية العنوان label و صناديق المدخلات Entry وسنكمل في مقالات لاحقة من السلسلة بقية العناصر. هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة: واجهات المستخدم الرسومية في بايثون باستخدام TKinter. مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون. حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون. الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون. مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون. حاوية العنوان label تعد حاوية عنوان label من أسهل العناصر التي يمكن إضافتها إلى النافذة الرئيسية وتُستخدم لتوضيح عناوين صناديق المدخلات Entry أو لعرض مخرجات نصية أو صورة. إنشاء حاوية العنوان داخل النافذة يتم اختيار اسم الكائن المطلوب ليمثل حاوية العنوان ويستخدم الصنف Label من مكتبة Tkinter ، ويعطى الصنف أولًا المكان الذي نريد وضع الحاوية فيه وهو النافذة الرئيسية، ومن ثم النص المراد عرضه داخل الحاوية باستخدام الخاصية text على النحو التالي: Label_name=Label(main_window, text="النص") تنشئ الشفرة التالية حاوية عنوان تعرض عبارة (واجهات المستخدم الرسومية في بايثون) ومن ثم تضعها على النافذة الرئيسية باستخدام الدالة pack: from tkinter import * main_window = Tk() main_window.title(" حاوية العنوان ") First_Label = Label(main_window, text= "واجهات المستخدم الرسومية في بايثون ") First_Label.pack() main_window.mainloop() بتشغيل الشفرة السابقة نحصل على النافذة التالية: حاوية العنوان خصائص حاوية العنوان label يمكننا تعديل الكثير من خصائص مظهر حاوية العنوان، النقاط التالية تستعرض أهم الخصائص التي من الممكن استخدامها: اللون بالإمكان تغيير لون النص والذي يعرف باسم foreground ويمكن كتابته اختصارًا fg، وكذلك تغيير لون الخلفية والذي يعرف باسم background ويكتب اختصارًا bg، ونستخدم إما صيغ نصية للألوان فنكتب اسم اللون المطلوب مثل: "white", "black", "red", "green", "blue", "cyan", "yellow", "magenta" أو يمكننا استخدام سلسلة تحدد نسبة الأحمر والأخضر والأزرق بالأرقام الست عشرية. على سبيل المثال: "#FFFF00" أصفر "#FFFFFF" أبيض "#00FF00" أخضر نوع الخط يُعرف الخط باستخدام الخاصية font وتعطى قيمة صفوف tuple مكونة من اسم الخط وحجمه، ومن الممكن تحديد ما إذا كان الخط عريضًا bold أو مائلًا italic مثال: ("Helvetica", "16") ("Times", "24", "bold italic") شكل مؤشر الفأرة بالإمكان التحكم بشكل المؤشر أثناء مروره على حاوية العنوان باستخدام الخاصية cursor والتي من الممكن أن تأخذ قيمًا مختلفة مثال على بعض القيم التي من الممكن إسنادها لها: "circle", "clock", "cross", "dotbox", "watch", "heart" وبطبيعة الحال قد يختلف شكل المؤشر اختلافًا طفيفًا مع اختلاف نظام التشغيل المستخدم. الحدود الخارجية والداخلية تترك الخاصية pad مساحة حول العنصر بمحيطه الخارجي عبر ضبط الخاصيتين التاليتين: pady تترك مساحة حول العنصر على الإحداثي الصادي. padx تترك مساحة حول العنصر على الإحداثي السيني. وتوجد أيضًا الخاصية ipad التي تترك مساحة حول العنصر بمحيطة الداخلي عبر ضبط الخاصيتين التاليتين: ipady تترك مساحة بين العنصر وحدوده الداخلية على المحور الصادي. ipadx تترك مساحة بين العنصر وحدوده الداخلية على المحور السيني. وتستخدم هذه الخصائص مع الدالة Pack التي ستضع الحاوية على النافذة الرئيسية. سنقوم بتجربة الخاصيات السابقة في برنامج متكامل، سنضيف رقة تعريف مكتوب بها نص بسيط بحجم 30 ونوع خط Stencil ونجعله ثخينًا ومائلًا، ونحدد لون الخلفية إلى أزرق باستخدام الصيغة النصية، مع لون نص أبيض باستخدام نظام الأرقام الست عشرية، ومؤشر فأرة يتغير إلى شكل نجمة عند مروره على حاوية العنوان، وسنترك مساحة حول الحاوية من حدودها الداخلية والخارجية، ستكون الشفرة على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" حاوية العنوان ") First_Label = Label(main_window, text="Sample text ",\ font=("Stencil", "30", "bold italic") ,\ fg ="#FFFFFF" , bg="blue", cursor ="star",) First_Label.pack(padx=50, pady=50 ,ipadx=100,ipady=100 ,side= TOP) main_window.mainloop() عند تشغيل الشفرة سنحصل على الشكل التالي: حاوية العنوان مخصصة تغيير النص قمنا بتحديد النص الذي نرغب بظهوره في حاوية العنوان أثناء إنشائها من خلال خاصية text، بالإمكان كذلك جعل النص فارغًا عند الإنشاء وتحديده في خطوة لاحقة، لتنفيذ ذلك نستخدم الخاصية textvariable ونسند لها قيمة كائن من الصنف StringVar، والذي نقوم بتعريفه ونختار له اسمًا لنفترض أنه mytext فتكون الشفرة على النحو التالي: Mytext= StringVar() Label_name=Label(main_window, textvariable=mytext) نستطيع إسناد قيمة له في خطوة لاحقة باستخدام الدالة set كما يلي: Mytext.set("sample text") بإمكاننا إعادة كتابة الشفرة السابقة بهذه الطريقة وسنحصل على نفس النتيجة: from tkinter import * main_window = Tk() main_window.title(" حاوية العنوان ") Mytext= StringVar() First_Label = Label(main_window, textvariable=Mytext,\ font=("Stencil", "30", "bold italic") ,\ fg ="#FFFFFF" , bg="blue", cursor ="star",) First_Label.pack(padx=50, pady=50 ,ipadx=100,ipady=100 ,side= TOP) Mytext.set("sample text") main_window.mainloop() إدراج صورة بالإمكان استبدال صورة بالنص الموجود في حاوية العنوان ونحتاج لفعل ذلك تعريف كائن من الصنف PhotoImage بتسميته باسم myphoto و سنعطيه باستخدام الخاصية file مسار الصورة (مكان تواجدها بالجهاز) على النحو التالي: myphoto = PhotoImage(file='Photo\path') ومن ثم نستخدم الخاصية image أثناء تعريف الحاوية ونسند لها قيمة الكائن الذي أنشأناه ستكون الشفرة كاملة على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" إدراج صورة ") myphoto = PhotoImage(file='Hsoub.png') First_Label = Label(main_window,image=myphoto) First_Label.pack(padx=50, pady=50 ,ipadx=100,ipady=100 ,side= TOP) main_window.mainloop() ونحصل على النتيجة التالية: حاوية عنوان بصورة استخدمنا في المثال السابق الصورة المسماة Hsoub.png وكانت موجودة في نفس مسار وجود ملف الشفرة، لذلك وضعنا اسمها مباشرة، ولو كانت في مكان مختلف لقمنا بتحديد مكان وجودها، للأسف الكائن PhotoImage يدعم فقط صيغ محدودة وهي: GIF, PGM, PPM, PNG ولو أردنا أن نعرض نصًا وصورة في نفس الحاوية يجب علينا أن نستعين بالخاصية compound والتي تحدد مكان ظهور الصورة بالنسبة للنص وتأخذ قيمة من الاحتمالات التالية: 'top','bottom', 'left', 'right', 'center','none' يعرض السطر التالي الصورة فوق النص: First_Label = Label(main_window,image=myphoto , text='شعار شركة حسوب' ,compound='top') وتكون النافذة بالشكل التالي: حاوية مدمجة صناديق المدخلات Entry تعتبر صناديق المدخلات من العناصر الأساسية لواجهات المستخدم الرسومية، لأنها تمكننا من قراءة المدخلات التي يدخلها المستخدم عبر/من لوحة المفاتيح، وتكون على شكل صندوق يسمح للمستخدم أن يدخل فيه نصًا. إنشاء صناديق المدخلات داخل نافذة يجب علينا تعريف كائن من الصنف Entry من مكتبة Tkinter حتى ننشئ مُدخلًا، ويُعطى الصنف أولًا المكان الذي نريد وضع المدخل فيه وهو النافذة الرئيسية، ومن ثم بإمكاننا تحديد عدة خيارات للمدخل، ويوضح السطر التالي عملية الإنشاء: First_Entry = Entry(main_window, option.........) يسبق صندوق المُدخلات في الغالب حاوية عنوان لبيان الغرض منه أو ما الذي يتوجب على المستخدم إدخاله، ويتم الاستغناء في بعض الحالات عن الحاوية وتبديلها بنص يوضع داخل الصندوق نفسه يبين الغرض منه، ويتم ذلك باستخدام الدالة insert وإعطائها مكان النص المراد ظهوره (يعطى قيمة صفر كبداية المدخل) وتعطى أيضًا النص المراد كتابته على النحو التالي: First_Entry.insert(0,’text’) ترسم الشفرة التالية صندوق مدخلات ليدخل المستخدم اسمه فيه على سبيل المثال ومن ثم يضيفه على النافذة الرئيسية باستخدام الدالة pack: from tkinter import * main_window = Tk() main_window.title(" إدراج مدخل") First_Entry = Entry(main_window ) First_Entry.insert(0,'الاسم') First_Entry.pack() main_window.mainloop() يظهر الشكل التالي عند تشغيل الشفرة: صندوق إدخال خصائص صندوق المدخلات يتميز صندوق المدخلات بالكثير من الخصائص التي تشبه ما تم الحديث عنه في حاوية العنوان، فيمكننا تغيير لون النص ولون الخلفية ونوع الخط وشكل المؤشر بنفس الطريقة وبنفس الخصائص المستخدمة مع حاوية العنوان . كما يمكننا تعديل حدود الصندوق باستخدام الخاصية bd لتكون أكثر سمكًا حيث أن القيمة الافتراضية لها هي 2، وكذلك نستطيع تغيير الحالة للصندوق باستخدام الخاصية state حيث يكون الصندوق فعالًا ويسمح بالكتابة فيه بالقيمة normal وهي الافتراضية، ويمكن تغييرها للقيمة disable والتي تجعله غير فعال ولا يسمح بالكتابة فيه. بتطبيق ذلك، يرسم السطر التالي صندوق مدخلات بحدود عرض بقيمة 5 مع تعطيل خاصية قبول المدخلات فيه: First_Entry = Entry(main_window, bd=10 , state="disable") ويكون بالشكل التالي: صندوق ادخال مخصص تمكننا الخاصية selectforeground من تحديد لون النص والخاصية selectbackground من تحديد لون خلفية النص المدخل إذا ماتم تحديده من المستخدم. الحصول على قيمة المُدخلات لنحصل على قيمة المدخل من المستخدم نستخدم الدالة get والتي ترجع ما أدخل في الحقل بصيغة نص: First_Entry.get() تُسند قيمة مدخلات المستخدم غالبًا إلى كائن من الصنف StringVar ونقوم بإعطائه للخاصية textvariable بعد عملية تعريفه على النحو التالي: mytext = StringVar() First_Entry = Entry(main_window, textvariable=mytext) ونستطيع استخدام الدالة get معه أيضًا للحصول على قيمة المدخل: mytext.get() يجب الانتباه إلى أن القيمة التي تعيدها الدالة get تكون على صيغة نص كما سبق وأشرنا، فعند إدخال الأرقام يجب تحويلها من نص إلى رقم باستخدام الدالة int أو الدالة float حسب نوع القيمة إذا ما أردنا استخدامها في العمليات الحسابية. يمكننا إضافة أهمية على المدخل بزيادة التركيز عليه باستخدام الدالة focus والتي ستقوم تلقائيًا بوضع المؤشر على المُدخل ليتمكن المستخدم من الكتابة مباشرة على النحو التالي: First_Entry.focus() إخفاء معلومات المدخلات تكون بعض القيم التي يدخلها المستخدم حساسة ويجب إخفائها أثناء الإدخال مثل كلمات السر مثلًا ويمكننا عمل ذلك باستخدام الخاصية show ونعطيها قيمة الرمز أو الحرف الذي نريد ظهورة، في المثال التالي سيظهر الرمز * بدلًا مما يقوم المستخدم بإدخاله: First_Entry = Entry(main_window, textvariable=mytext, show='*') استجابة صندوق المدخلات نستطيع ربط صندوق المدخلات بدالة معينة تتنفذ عندما يقوم المستخدم بالنقر على زر الإدخال Enter ونستخدم الدالة bind لنربط صندوق المدخلات بالنقر على Enter كالتالي: First_Entry.bind('<Return>',handler) حيث أن handler هو اسم الدالة التي سيتم تنفيذها، ونستطيع كذلك ربط العديد من الأزرار بنفس الطريقة مع الدالة باستخدام اسم الزر المناسب، مثل زر المسافة Space وزر الهروب Escape وزر المسح Delete. لنكتب الشيفرة التالية حيث سننشئ صندوق مدخلات وعند نقر المستخدم على زر الإدخال Enter نقوم بطباعة عدد الأحرف التي تم إدخالها في حاوية العنوان: from tkinter import * main_window = Tk() main_window.title("Entry response ") def handler(e): L=myentertext.get() mylabeltext.set(len(L)) myentertext = StringVar() mylabeltext= StringVar() First_Entry = Entry(main_window, textvariable=myentertext,bd=10 ) First_Entry. pack(side= TOP) First_Entry.focus() tag_label=Label(main_window,text='عدد الأحرف') tag_label.pack(side= BOTTOM) First_Label = Label(main_window, textvariable=mylabeltext ) First_Label.pack(side= BOTTOM) First_Entry.bind('<Return>',handler) main_window.mainloop() عند تجربة الشفرة ستظهر النتيجة التالية: استجابة المدخلات تطبيق الآلة الحاسبة (الجزء الثالث) لننتقل لجزئية التطبيق على مشروع آلتنا الحاسبة، كنا قد رسمنا النافذة الرئيسية للآلة و وضعنا داخلها إطارين بحاوية عنوان العلوية للمدخلات والسفلية لأزرار العمليات والأرقام، في هذا التطبيق سنضع في الإطار الأول حاوية عنوان نسميها input_label نكتب فيها عبارة "أدخل المعادلة الحسابية"، على جهة اليمين ونحددها بلون خلفية من درجات الأزرق بقيمة "#007CFF" ولون خط أبيض، وفي الجهة اليسرى نضع صندوق مدخلات نسميه input_field يعرض الأرقام والعمليات التي ينقر عليها المستخدم، إذ حددنا له عرضًا يتناسب مع مقاس النافذة بمقدار 18، وحددنا له نوع الخط 'arial' بمقياس 12 وجعلناه ثخينًا، وقمنا بتعريف متغير من نوع StringVar أسميناه input_text ليكون محتواه متغيرًا يختلف مع كل نقرة من المستخدم على الأزرار، تكون شفرتهما على النحو التالي: input_label=Label(input_frame,text="أدخل المعادلة الحسابية ", bg="#007CFF",fg="white") input_field = Entry(input_frame, width=18, font=('arial', 12, 'bold'),textvariable=input_text) لوضع هذه العناصر في داخل الإطار استخدمنا خاصية grid وأضفنا حدودًا داخلية على المحور الصادي بمقدار 10، ندمج هذه الإضافات على الشفرة السابقة ونحصل على التالي: from tkinter import * from ctypes import windll windll.shcore.SetProcessDpiAwareness(1) mycalculator = Tk() mycalculator.title("آلة حاسبة بسيطة") mycalculator.geometry("575x740") mycalculator.resizable(False, False) 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() input_text = StringVar() 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) mycalculator.mainloop() ونحصل على النتيجة التالية: واجهة الآلة الحاسبة الثانية يتبقى لآلتنا جزئية الإطار السفلي والذي يحتوي على الأزرار التي تحوي الأرقام والعمليات الحسابية، وهذا ما سنتناوله في المقال القادم كيفية إدراج الأزرار وربطها بوظائف معينة تقوم بها عند النقر عليها. المصادر Tkinter Label Python - Tkinter Colors Python - Tkinter Fonts Python - Tkinter Cursors Tkinter PhotoImage Tkinter Entry Python Tkinter Entry ?How to bind the spacebar key to a certain method in Tkinter ?How to bind the Escape key to close a window in Tkinter Tkinter Event Binding اقرأ أيضًا المقال التالي: الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون المقال السابق: واجهات المستخدم الرسومية في بايثون باستخدام TKinter برمجة الواجهات الرسومية باستخدام Tkinter النسخة العربية الكاملة من كتاب: البرمجة بلغة بايثون
-
تحدثنا في هذه السلسلة عن عناصر الواجهة الرسومية Widgets ثم بدأنا بشرح أهم العناصر فيها وهي حاوية العنوان label وصناديق المدخلات Entry ثم انتقلنا إلى الأزرار Buttons ومربعات الرسائل messagebox ونستكمل سلسلتنا التعليمية في هذا المقال لواجهات المستخدم الرسومية بعنصرين مهمين في الواجهات لعرض خيارات مختلفة للمستخدم هما مربعات الاختيار Checkbutton و أزرار الانتقاء Radio Button، إذ سنستعرض طريقة إنشائها وخصائصها، ثم ننتقل بعد ذلك إلى الحديث عن القوائم Menus وخصائصها. هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة: واجهات المستخدم الرسومية في بايثون باستخدام TKinter. مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون. حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون. الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون. مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون. مربعات الاختيار Checkbutton تُستخدم مربعات الاختيار لعرض مجموعة من الخيارات للمستخدم يستطيع أن يختار أكثر من خيار واحد من بينها عن طريق تحديد المربع الماثل أمام كل خيار، ونستطيع استعادة قيمة الخيار الذي تم تحديده وكذلك ربطه بدالة محددة لتقوم بعمل معين عندها. إنشاء مربعات الاختيار داخل النافذة يتم اختيار اسم الكائن المطلوب ليمثل مربعات الاختيار ويستخدم الصنف Checkbutton من مكتبة Tkinter، ويعطى الصنف أولًا المكان الذي نريد وضع المربع فيه وهو النافذة الرئيسية، ومن ثم نص الخيار المراد عرضه أمام مربع الاختيار باستخدام الخاصية text على النحو التالي: Button1 = Checkbutton(main_window, text = "الخيار الأول ") تكون قيمة المربع عند عدم اختياره صفر افتراضيا وقيمة 1 عند الاختيار وإذا أردنا تغيير ذلك نستخدم الخاصية onvalue ونعطيها القيمة المطلوبة عند اختيار المربع والخاصية offvalue ونعطيها القيمة عند عدم الاختيار، ويوضح المثال التالي المقصود: Button1 = Checkbutton(main_window, text = "الخيار الأول ", onvalue = "True",offvalue = "False") ونضيف عدة خصائص مع مربع الاختيار منها command ونربط بها الدالة التي نريد نداءها عند تغير حالة المربع من مُختار إلى غير مختار، ونستطيع الحصول على قيمة الاختيار عند ربط الخاصية variable بمتغير فإذا كانت القيمة رقمية يكون من نوع IntVar وإذا كانت غير ذلك من نوع StringVar، وتكون شفرة مربع الاختيار كاملة على النحو التالي: Checkbutton1 = IntVar() Button1 = Checkbutton(main_window, text = "الخيار الأول ", onvalue =2 ,offvalue = 1, variable = Checkbutton1 , command=get_choice) حيث أن get_choice هي الدالة التي سيتم ندائها عند تغير الحالة، وفي النهاية نضيفها للدالة الرئيسية باستخدام الدالة pack. خصائص مربعات الاختيار نستطيع كما في كل عناصر واجهات المستخدم الرسومية أن نعدل خصائصها، مثل تغيير لون النص ولون الخلفية ونوع الخط وشكل المؤشر بنفس الطريقة السابقة وبنفس الخصائص المستخدمة، فنستطيع مثلًا التعديل على حالة المربع باستخدام الدالة select لاختياره ونلغي عنه الاختيار باستخدام الدالة deselect كما يلي: Button1.select() أو Button1.deselect() أزرار الانتقاء Radio Button أزرار الانتقاء شبيهة جدًا بمربعات الاختيار فهي تعرض للمستخدم عدة خيارات ولكن هذه المره عليه أن يختار أو ينتقي واحدًا منها فقط. إنشاء أزرار الانتقاء داخل النافذة يتم اختيار اسم الكائن المطلوب ليمثل مربعات الاختيار ويستخدم الصنف Radiobutton من مكتبة Tkinter، ويعطى الصنف أولًا المكان الذي نريد وضع المربع فيه وهو النافذة الرئيسية، ومن ثم نص الخيار المراد عرضه أمام زر الانتقاء باستخدام الخاصية text على النحو التالي: Button1 = Radiobutton(main_window, text = "الخيار الأول ") شفرة إنشاء الأزرار شبيهة جدًا بمربعات الاختيار، وتختلف عنها بأن خاصية variable يجب أن تحتوي على متغير واحد تشترك فيه جميع الخيارات قد يكون من نوع IntVar إذا كانت قيم الخيارات رقمية أو نوع StringVar إذا كانت غير ذلك، كذلك نستخدم الخاصية value لنعطي كل خيار قيمة مختلفة عن الآخر. Button1 = Radiobutton(main_window, text = "الخيار الأول ", variable = Var1, value = 1) في هذا المثال يجب على جميع أزرار الانتقاء ان يكون لها نفس هذه القيمة variable = Var1، ونستخدم الخاصية command لنربطها بالدالة التي ستُسدعى في كل مرة يتم فيها تغيير الاختيار من بين خيارات أزرار الانتقاء المطروحة. خصائص أزرار الانتقاء نستطيع كما في كل عناصر واجهات المستخدم الرسومية أن نعدل خصائصها كتغيير لون النص ولون الخلفية ونوع الخط وشكل المؤشر بنفس الطريقة السابقة وبنفس الخصائص المستخدمة، وكما في مربعات الاختيار نستطيع استخدام الدالة select والدالة deselect مع كل عنصر، سنعرض في المثال التالي للمستخدم مجموعة أزرار انتقاء ليختار منها واحدا وتعرض حاوية عنوان اسم الخيار الذي اختاره المستخدم: from tkinter import * main_window = Tk() main_window.title("أزرار الانتقاء ") Var1 = StringVar() def sel(): selection = "لقد قمت باختيار " + str(Var1.get()) label.config(text = selection) B1=Radiobutton(main_window, text = "الخيار الأول ",variable = Var1, value = "الأول", command=sel) B2=Radiobutton(main_window, text = "الخيار الثاني ",variable = Var1, value = "الثاني", command=sel) B3=Radiobutton(main_window, text = "الخيار الثالث ",variable = Var1, value = "الثالث", command=sel) B1.pack() B2.pack() B3.pack() label = Label(main_window) label.pack() main_window.mainloop() نحصل على النتيجة التالية: أزرار الانتقاء القوائم Menus قد يحتوي البرنامج الذي صمم باستخدام واجهات المستخدم الرسومية الكثير من الوظائف والخصائص، فتبرز الحاجة إلى مزيد من الترتيب والتنظيم في عرضها، ومن العناصر المساعدة على فعل ذلك القوائم Menus، فهي تضفي المزيد من الترتيب على مظهر النافذة حيث تقوم بتجميع العمليات المتشابهة وإدراج تصنيفات لها. تدعم مكتبة Tkinter القوائم وتعرضها بمظهر مشابه لأشكال القوائم في نظام التشغيل الذي يعمل عليه البرنامج، ويمكن عدّ قائمة Tkinter على أنها مجموعة من عدة عناصر واجهة المستخدم الأخرى المدمجة في عنصر واحد، لذلك تعتبر عملية إنشائها أكثر صعوبة من بقية عناصر واجهة المستخدم، ولكن الجانب الإيجابي هو أن استخدام القائمة بشكل صحيح في التطبيق يحسن الوظائف بشكل كبير ويجعلها تبدو احترافية. إنشاء القائمة داخل النافذة يتطلب إنشاء القائمة عدة خطوات: الخطوة الأولى،إنشاء كائن ليمثل القائمة الرئيسية ويستخدم المصنف Menu من مكتبة Tkinter، ويعطى الصنف المكان الذي نريد وضع الإطار فيه وهو النافذة الرئيسية على النحو التالي: main_menu=Menu(main_window) الخطوة الثانية، نحتاج إلى ربط القائمة الرئيسية main_menu بالنافذة الرئيسية main_window باستخدام الخاصية menu وبما أننا نقوم بتعديل خصائص النافذة بعد عملية إنشائها، فسنحتاج إلى استخدام الدالة config على النحو التالي: main_window.config(menu=main_menu) الخطوة الثالثة، نحتاج إلى إضافة القوائم الفرعية التي ستنسدل من القائمة الرئيسية مثل قائمة ملف، تعديل، المظهر والخيارات ونحوها، ونحتاج لفعل ذلك إلى إنشاء كائن من الصنف Menu ويعطى المكان الذي نريد وضعه فيه وهو القائمة الرئيسية: file_menu = Menu(main_menu) بعد ذلك نقوم بربطه مع القائمة الرئيسية باستخدام الدالة add_cascade وتعطى رقعة التعريف label التي يكتب عنوان هذه القائمة فيه، واسم القائمة file_menu: main_menu.add_cascade( label="ملف", menu=file_menu) ستكون الشفرة كاملة على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" القوائم ") main_menu=Menu(main_window) main_window.config(menu=main_menu) file_menu = Menu(main_menu) main_menu.add_cascade( label="ملف", menu=file_menu ) main_window.mainloop() وسنحصل على النافذة التالية: نافذة بقائمة في هذه النافذة قائمة ملف فارغة، نحتاج إلى إضافة عناصر في هذه القائمة، لعمل هذا نستخدم الدالة add_command، وتعطى حاوية عنوان لاسم عنصر القائمة باستخدام الخاصية label وكذلك تعطى الأمر الذي يجب تنفيذه عند النقر على عنصر القائمة باستخدام الخاصية command: file_menu.add_command(label=’name’ , command=………..) سنضيف على المثال السابق عنصر للقائمة ملف تحت اسم خروج، وتغلق النافذة الرئيسية عند النقر عليه ونستخدم للإغلاق الأمر التالي: main_window.destroy وتكون الشفرة كاملة على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" القوائم ") main_menu=Menu(main_window) main_window.config(menu=main_menu) file_menu = Menu(main_menu) main_menu.add_cascade( label="ملف", menu=file_menu) file_menu.add_command(label='خروج', command=main_window.destroy) main_window.mainloop() نحصل عند تشغيل الشفرة على النافذة التالية: نافذة بقائمة تحوي خيارات بإمكاننا عمل قائمة فرعية لتكون مدرجة داخل قائمة أخرى مثلًا إذا أردنا إضافة قائمة تصدير داخل القائمة ملف فعلينا إنشاء كائن من الصنف Menu ومن ثم وضعه على القائمة ملف باستخدام الدالة add_cascade على النحو التالي: export_menu = Menu(file_menu) file_menu.add_cascade( label="تصدير", menu=export_menu) خصائص القوائم يمكننا تغيير الكثير من خصائص القوائم كتغيير لون النص fg و لون الخلفية bg و نوع الخط font و شكل المؤشر cursor، كذلك يمكننا التحكم بحالتها باستخدام الخاصية state حيث أنه افتراضيًا يكون فعالًا normal ويمكننا تغييره إلى غير فعال disable. تضع Tkinter افتراضيًا خطًا متقطعًا في بداية القائمة بإمكاننا إخفاءه باستخدام الخاصية tearoff وإعطائها قيمة False أثناء إنشاء القائمة على النحو التالي: file_menu = Menu(main_menu,tearoff=False) عندما تحتوي القائمة على الكثير من العناصر، فمن الجيد تجميع المتشابه منها وإدراجها متسلسة ووضع فاصل بين مجموعة وأخرى، ونستخدم لعمل ذلك الدالة add_separator() مع اسم القائمة على النحو التالي: file_menu.add_separator() تطبيق الآلة الحاسبة (الجزء الخامس) قمنا في الدروس السابقة برسم نافذة الآلة مع وضع إطارين عليها واحد للمدخلات والآخر لأزرار الأرقام والعمليات، وقمنا بربط الأزرار بالدوال المطلوبة لتنفيذ العمليات الحسابية، وتوصلنا للشكل التالي: واجهة الآلة الحاسبة الرابعة سنطبق ما تعلمناه عن القوائم و نضيف لتطبيق الآلة قائمة رئيسة نسميها الخيارات، بتنفيذ نفس الخطوات السابقة، فنبدأ بإنشاء كائن ليمثل القائمة الرئيسية نسمية main_menu، بعدها نربط الكائن بنافذتنا الرئيسية mycalculator. main_menu=Menu(mycalculator) mycalculator.config(menu=main_menu) بعد ذلك نضيف قائمتنا الوحيدة نسميها option_menu ونعنونها بخيارات ونضيفها على القائمة: option_menu = Menu(main_menu) main_menu.add_cascade( label="الخيارات", menu=option_menu) نضيف في قائمة الخيارات خيارين، الأول بعنوان (حول التطبيق) يعرض مربع رسائل من نوع showinfo تعرض معلومات عن الآلة، ونضيف دالة about_MSG تعرض مربع الرسائل ونربطها باستخدام الأمر command مع عنصر القائمة على النحو التالي: def about_MSG(): showinfo(title='حول التطبيق', message='تم تصميم هذه الآلة خلال سلسلة دروس \n'+ 'تعلم استخدام واجهات المستخدم الرسومية \n'+ 'في بايثون باستخدام '+'\nTkinter') option_menu.add_command(label='حول التطبيق', command=about_MSG) يغلق الخيار الثاني بعنوان "خروج" النافذة: option_menu.add_command(label='خروج',command=mycalculator.destroy) وتظهر الآلة بشكلها النهائي كما يلي: واجهة الآلة الحاسبة بقوائم مربع رسائل حول التطبيق وبهذا نكون قد أنهينا تطبيق الآلة الحاسبة كاملًا. المصادر Python Tkinter Check Button. Tkinter Checkbox. Python Tkinter Checkbutton Widget. Tkinter Radio Button. Python Tkinter Radio Button. Python Tkinter Radiobutton Widget. Python - Tkinter Radiobutton. Tkinter Menu. Python Tkinter Menu. اقرأ أيضًا المقال السابق: الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون واجهات المستخدم الرسومية في بايثون باستخدام TKinter المرجع الشامل إلى تعلم لغة بايثون النسخة الكاملة من كتاب البرمجة بلغة بايثون
-
تحدثنا في المقال السابق عن الواجهات الرسومية للتطبيقات باستخدام TKinter، وتطرقنا للنافذة الرئيسية التي هي أساس أي تطبيق مكتوب باستخدام الواجهات وشرحنا مجموعة من خصائصها، سنكمل في هذا المقال ونتحدث عن العناصر التي نضعها على النافذة الرئيسية، والتي يطلق عليها مسمى Widgets. هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة: واجهات المستخدم الرسومية في بايثون باستخدام TKinter. مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون. حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون. الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون. مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون. Widgets هي عبارة عن عناصر التحكم التي نضعها على النافذة ليتمكن المستخدم من التفاعل معها، حيث توضح له معنى أو تطلب منه أدخال أمر معين أو تأخذ منه أمرًا لتنفيذ مهمة مطلوبة مثل الأزرار، ومربعات الإدخال وحاويات العناوين ومربعات الإختيار والقوائم وغيرها، الجدول التالي يوضح مجموعة من أهم العناصر التي يمكننا إضافتها على النافذة: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } اسم العنصر الوصف Label حاوية العنوان يستخدم لعرض سلسلة نصية أو صورة . Message الرسالة شبيه بحاوية العنوان يستخدم لعرض سلسلة نصية مكونة من أكثر من سطر. Buttons الأزرار يستخدم لإضافة أزرار تفاعلية في النافذة عند النقر عليها يتم نداء دالة معينة تؤدي وظيفة معينة. Entry صندوق المدخلات يستخدم لقراءة المدخلات التي يكتبها المستخدم باستخدام لوحة المفاتيح Frame الإطار يستخدم لترتيب العناصر داخل النافذة بحيث يكون كالحاوية لهم. Menus القوائم تستخدم لعرض قائمة منسدلة أو منبثقة مكونة من مجموعة من أزرار القائمة. Menubutton أزرار القائمة عنصر عبارة عن مزيج يدمج ما بين الأزرار والقائمة بحيث يكون من ضمن مجموعة من الخيارات عند النقر عليه يتم تنفيذ أمر معين. ListBox مربع القائمة يستخدم لعرض قائمة يختار المستخدم منها عنصر. Checkbutton صناديق التأشير عبارة عن مربعات تسمح للمستخدم بأن يختار منها (تسمح بأكثر من خيار) وتكون بوضعية مفعل أو غير مفعل. Radiobutton أزرار الانتقاء شبيهة بصناديق التأشير تستخدم بالغالب كمجموعة خيارات لابد من اختيار واحد منها فقط. يوجد جيلين من العناصر في مكتبة Tkinter: العناصر الكلاسيكية التقليدية والتي تم طرحها عام 1991. العناصر الحديثة التي تمت إضافتها عام 2007 تسمى عناصر TTk اختصارًا لكلمة Tk themed تستبدل العديد من العناصر القديمة وليس كلها . من مميزات استخدام الجيل الجديد من العناصر الحديثة أن مظهر العناصر يختلف باختلاف نظام تشغيل جهاز الحاسب الذي تعمل عليه ليصبح متوافقًا معه، كذلك تسمح العناصر الحديثة بالفصل بين خصائص مظهرها وبين الأوامر التفاعلية التي تقوم بها في ملفات تنسيق مختلفة عن بعضها، ويعتبر من الجيد دائمًا استخدام الجيل الجديد من العناصر باستخدام القالب tkinter.ttk، السطر التالي يستدعي العناصر الكلاسيكية والجديدة: from tkinter import * from tkinter import ttk توضح الشفرة التالية كيفية إنشاء حاوية عنوان Label و زرار Button باستخدام الطريقة الكلاسيكية: from tkinter import * main_window = Tk() # النافذة الرئيسية main_window.title(" (الطريقة الكلاسيكية) ") classicL=Label(main_window, text='Classic Label') classicL.pack() classicB=Button(main_window, text='Classic Button') classicB.pack() main_window.mainloop() توضح الشفرة التالية كيفية إنشائهما بإستخدام الطريقة الحديثة بإضافة اسم الصنف ttk قبل اسم العنصر: from tkinter import ttk main_window = Tk() # النافذة الرئيسية main_window.title("(الطريقة الحديثة ) ") ThemedL=ttk.Label(main_window, text='Themed Label') ThemedL.pack() ThemedB=ttk.Button(main_window, text='Themed Button') ThemedB.pack() main_window.mainloop() ستبدو المخرجات عند تشغيل الشيفرة بالشكل التالي: الطريقة الحديثة والكلاسيكية لعناصر واجهات المستخدم قد لا يبدو الاختلاف بينهما واضحًا، لكن كما سبق وقلنا يعتمد المظهر كثيرًا على نوع نظام التشغيل الذي تعمل عليه. التحكم بخصائص العناصر جميع هذه العناصر لها مجموعة متنوعة من الخصائص بخيارات مختلفة، تختلف باختلاف العناصر حسب ما يتميز به كل عنصر، كما توجد خصائص مشتركة بين غالبية العناصر مثل: لون الخلفية، ولون الخلفية عندما يكون العنصر فعالًا، والنص المكتوب، ولون النص ونوع الخط، ولون النص عندما يكون العنصر فعالًا، والعرض والارتفاع بالبكسل، وشكل المؤشر …إلخ. ويُسمح لنا بالتحكم فيها من خلال 3 طرق إما في وقت الإنشاء من خلال معاملات الدوال أو بعد إنشاء العنصر من خلال استخدام القواميس أو الدالة config: 1. في وقت الإنشاء من خلال معاملات الدوال keyword arguments وهذه هي الطريقة التي استخدمناها حتى الآن لوضع نص في حاوية العنوان أو في الزر كما في المثال السابق بتحديد اسم معامل الدالة بنوع الخاصية المطلوبة وهي text ومن ثم إعطائه قيمة النص المطلوبة أو مثلًا خاصية لون الخط foreground ونضعه مثلًا أزرق blue. L=Label(main_window, text='نص باللون الأزرق' ,foreground='blue') سيبدو الشكل على النحو التالي : إضافة خصائص وقت الإنشاء 2. بعد إنشاء العنصر من خلال استخدام القواميس dictionary index تفعل الشفرة التالية نفس الشيء ولكن من خلال الاستفادة من فكرة القواميس، فنقوم بمعاملة العنصر كقاموس ونستخدم اسم الخاصية المراد وضع قيمة لها كمفتاح للقاموس ونضع القيمة المرغوبة على النحو التالي: L=Label(main_window) L['text']='نص باللون الأزرق' ['foreground']= 'blue' 3. بعد إنشاء العنصر باستخدام الدالة config سنكرر نفس ما قمنا به ولكن باستخدام الدالة config وإرسال المعاملات المطلوب تعديلها بشكل مشابه للطريقة الأولى على النحو التالي: L=Label(main_window) L.config(text='نص باللون الأزرق' ,foreground='blue') كيفية وضع العناصر على النافذة يوجد ثلاثة طرق مختلفة لوضع العناصر على النافذة الرئيسية باستخدام ثلاثة دوال: الدالةPack: تضع العناصر على النافذة في مجموعة من المربعات الطولية والأفقية وهي محدودة بأربعة خيارات: يمين، يسار، أسفل، أعلى النافذة. الدالة Place: تضع العناصر على النافذة باستخدام الإحداثيات السينية X والصادية Y في المستوي الثنائي. الدالة grid: تضع العناصر على النافذة باستخدام شبكة ثنائية مكونة من أعمدة وصفوف. إضافة العناصر باستخدام الدالة Pack تعد الدالة Pack أسهل طريقة لوضع العناصر على النافذة، و ترتب العناصر بجانب بعضها البعض عموديًا أو افقيًا بدلًا من تحديد الموضع الدقيق للعنصر، بكل بساطة يتم نداء الدالة بعد اسم العنصر المطلوب وضعه على النافذة كما شاهدنا في الأمثلة السابقة على النحو التالي: Widget_name.pack() يمكن التحكم بمكان العنصر من خلال استخدام الخاصية side والتي يمكننا إعطائها 4 قيم مختلفة: Side = LEFT or RIGHT or TOP or BOTTOM سنرسم نافذة رئيسية نضيف لها 3 حاويات عنوان Label باسم L1,L2,L3 على الترتيب باستخدام الدالة Pack نضع لكل حاوية نصًا بلون أبيض باستخدام الخاصية fg وهي اختصار foreground أي لون النص، وخلفية بلون مختلف لكل حاوية باستخدام الخاصية bg وهي اختصار Background أي لون الخلفية، واستخدمنا الخاصية pady لتبعد كل حاوية عن الأخرى مسافة 20 بكسل على المحور الصادي، ستكون الشفرة على النحو التالي: from tkinter import * main_window = Tk() L1 = Label(main_window, text="أحمر",bg="red", fg="white") L1.pack(pady=20, side= TOP) L2 = Label(main_window, text="أخضر", bg="green", fg="white") L2.pack(pady=20, side= TOP) L3 = Label(main_window, text="أزرق", bg="blue", fg="white") L3.pack(pady=20, side= TOP) main_window.mainloop() سنعيد تشغيل الشيفرة أكثر من مرة وسنستخدم في كل مرة اتجاهًا مختلفًا للخاصية side ونرى كيف تقوم الدالة بترتيبهم مع بعضهم البعض في النافذة، عموديا عند استخدام الخيار TOP أو BOTTOM وأفقيًا عند اختيار LEFT أو RIGHT سنحصل على النتائج التالية: استخدام الدالة pack كما أشرنا آنفًا، تترك الخاصية pad مساحة حول العنصر بمحيطه الخارجي تتمثل فيه الخاصيتين التاليتين: pady تترك مساحة حول العنصر على الإحداثي الصادي . padx تترك مساحة حول العنصر على الإحداثي السيني. وتوجد أيضًا الخاصية ipad التي تترك مساحة حول العنصر بمحيطه الداخلي تتمثل في الخاصيتين التاليتين: ipady تترك مساحة بين العنصر وحدوده الداخلية على المحور الصادي. ipadx تترك مساحة بين العنصر وحدوده الداخلية على المحور السيني. تضع الشفرة التالية حدودًا حول العنصر من محيطه الخارجي ومحيطه الداخلي: from tkinter import * main_window = Tk() L1 = Label(main_window, text="أحمر",bg="red", fg="white") L1.pack(padx=150 , pady=50 ,ipadx=150,ipady=200 ,side= TOP) main_window.mainloop() فنحصل على الشكل التالي: استخدام الخاصية pad و ipad إضافة العناصر باستخدام الدالة place تستخدم الدالة place الإحداثيات السينية والصادية لوضع العناصر على النافذة، فيبدأ رسم العنصر من الزاوية العلوية اليسرى، وسنعيد استخدام الشفرة السابقة مع تبديل الدالة Pack إلى الدالة place وسنحاول وضع العناصر أسفل بعضها البعض متدرجة فنكتب الشفرة على النحو التالي: from tkinter import * main_window = Tk() L1 = Label(main_window, text="أحمر",bg="red", fg="white") L1.place(x=0, y=0) L2 = Label(main_window, text="أخضر", bg="green", fg="white") L2.place(x=50, y=40) L3 = Label(main_window, text="أزرق", bg="blue", fg="white") L3.place(x=110, y=80) main_window.mainloop() ونحصل على النتيجة التالية: استخدام الدالة place قد لا يكون استخدام الدالة place متوافقًا مع جميع شاشات الأجهزة، لو قمت بتشغيل الشفرة السابقة على جهاز يعمل بنظام تشغيل ويندوز بدقة شاشة 1024* 768 فستظهر العناصر بشكل متناسق، بينما لو اختلفت دقة الشاشة وكانت عالية الدقة مثلًا فستظهر العناصر شديدة الصغر ومتداخلة، وعلى العكس لو كانت الدقة منخفضة قد لا تظهر العناصر كاملة، لذلك يفضل تجنب استخدامها قدر المستطاع حتى لا نقع في مثل هذه المشاكل عند اختلاف الدقة. إضافة العناصر باستخدام الدالة grid تقسم الدالة grid النافذة الرئيسية إلى مجموعة من الأعمدة والصفوف بشكل افتراضي، لتكون بشكل تقريبي كالشبكة فتوضع العناصر فيها بتحديد رقم العمود ورقم الصف، يبدأ الترقيم من الصفر، وسنعيد ترتيب عناصرنا كما المثال السابق باستخدام الدالة grid على النحو التالي: from tkinter import * main_window = Tk() L1 = Label(main_window, text="أحمر",bg="red", fg="white") L1.grid(row=0, column=0) L2 = Label(main_window, text="أخضر", bg="green", fg="white") L2.grid(row=1, column=3) L3 = Label(main_window, text="أزرق", bg="blue", fg="white") L3.grid(row=2, column=6) main_window.mainloop() وسنحصل على نفس شكل النافذة السابق. ومن الخصائص التي يمكن التحكم بها لهذه الشبكة هي عرض الأعمدة والصفوف وقد قدمت لنا مكتبة Tkinter دالتين للتحكم بإعدادات الشبكة قبل بدء وضع العناصر عليها وهما الدالة columnconfigure والتي تأخذ رقم العمود والدالة rowconfigure والتي تأخذ رقم الصف ومن ثم تُعطى الدالة العرض المراد تحديده لكلٍ منهما وتكتب على النحو التالي: main_window.columnconfigure(index, weight) main_window.rowconfigure(index, weight) حيث تمثل index رقم الصف أو العمود وتمثل weight العرض المراد تحديده لهما، بالطبع العرض يكون كنسبة وتناسب مع بقية الأعمدة في الشبكة. كما نستطيع أيضًا أن نستخدم مع هذه الدالة الخاصيتان pad و ipad بالنفس الطريقة التي سبق شرحها. الإطارات Frames تعد الإطارات من العناصر المهمة لواجهات المستخدم الرسومية، فهي تستخدم لتجميع وتنظيم العناصر الأخرى بداخلها فتكون بمثابة الحاوية لهم، وتكون بمثابة مساحات مستطيلة توضع على النافذة الرئيسية لتنظيم تخطيط النافذة وترتيب وضع أماكن بقية العناصر عليها، كما يمكننا إنشاء إطار بداخل إطار آخر مما يعطينا قدرة أكبر على الترتيب. والإطارات بالنسبة للنافذة كما الهيكل العظمي للجسد يساعد على استقامته ويعطيه المظهر الملائم والهيئة المطلوبة. إنشاء الإطار داخل النافذة يجري اختيار اسم المتغير المطلوب ليمثل الإطار ويستخدم الصنف Frame من مكتبة Tkinter، ويعطى الصنف أولًا المكان الذي نريد وضع الإطار فيه وهو النافذة الرئيسية، ومن ثم بإمكاننا إضافة بقية الخصائص على النحو التالي: First_frame= Frame (main_window) خصائص الإطار يمكننا تغيير الكثير من خصائص الإطار كتعديل عرض width وطول height الإطار وكذلك تغيير لون الخلفية bg، وسمك الحدود bd، ونوع الحدود relief حيث يمكن إعطاءها قيم مختلفة مثل: raised, flat, ridge, groove , sunken. الشفرة التالية ترسم إطارين على النافذة الرئيسية أحدهما أخضر على اليمين والآخر أزرق على اليسار باستخدام الدالة pack: from tkinter import * main_window = Tk() main_window.title(" الإطارات ") right_frame=Frame(main_window,width=300,height=300,bg='green') right_frame.pack(side='right') left_frame=Frame(main_window,width=300,height=300,bg='blue') left_frame.pack(side='left') main_window.mainloop() عند تشغيل الشفرة نحصل على التالي: نافذة بإطار كما قلنا سابقًا، الهدف الأساسي من الإطارات تنظيم النافذة، سنقوم برسم نافذة تحتوي على عدة إطارات في كل اتجاه، و سنوزع العناصر فيها على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" الإطارات ") top_frame=Frame(main_window,bg='red') top_frame.pack(side='top') top_button=Button(top_frame,text=' زرار في إطار علوي' ) top_button.pack(padx = 40, pady = 40) right_frame=Frame(main_window,bg='green') right_frame.pack(side='right') right_button=Button(right_frame,text=' زرار في إطار على اليمين' ) right_button.pack(padx = 40, pady = 40) left_frame=Frame(main_window,bg='blue') left_frame.pack(side='left') right_button=Button(left_frame,text=' زرار في إطار على اليسار' ) right_button.pack(padx = 40, pady = 40) bottom_frame=Frame(main_window,bg='yellow') bottom_frame.pack(side='bottom') bottom_button=Button(bottom_frame,text=' زرار في إطار سفلي' ) bottom_button.pack(padx = 40, pady = 40) main_window.mainloop() وسنحصل على الشكل التالي: نافذة بإطارات ملونة الإطارات بحاوية عنوان LabelFrame هي نوع مخصص من الإطارات حيث تكون كالإطارات العادية من حيث أنها تكون حاوية لعناصر واجهات المستخدم الرسومية وتزيد عليها باحتوائها على حاوية عنوان تزيد من وضوح الهدف من الإطار وإظهارًا لمزيد من الترتيب في النوافذ المعقدة التي تحتوي الكثير من العناصر. تُنشأ الإطارات بحاوية عنوان باختيار اسم المتغير المطلوب ليمثل الإطار ويُستخدم الصنف LabelFrame من مكتبة Tkinter لذلك، ويعطى الصنف أولًا المكان الذي نريد وضع الإطار فيه وهو النافذة الرئيسية، ومن ثم نعطيه النص الذي نريد إظهاره كعنوان للإطار باستخدام الخاصية text ومن ثم يمكننا إضافة بقية الخصائص على النحو التالي: labeled_frame=LabelFrame(main_window,bd=10,text="test") سنعيد كتابة الشفرة السابقة باستخدام الإطارات بحاوية عنوان، وتكون الشفرة كاملة على النحو التالي: from tkinter import * main_window = Tk() main_window.title(" الإطارات ") top_frame=LabelFrame(main_window,text="علوي",bg='red') top_frame.pack(side='top') top_button=Button(top_frame,text=' زرار في إطار علوي' ) top_button.pack(padx = 40, pady = 40) right_frame=LabelFrame(main_window,text="أيمن",bg='green') right_frame.pack(side='right') right_button=Button(right_frame,text=' زرار في إطار على اليمين' ) right_button.pack(padx = 40, pady = 40) left_frame=LabelFrame(main_window,text="أيسر",bg='blue') left_frame.pack(side='left') right_button=Button(left_frame,text=' زرار في إطار على اليسار' ) right_button.pack(padx = 40, pady = 40) bottom_frame=LabelFrame(main_window,text="سفلي",bg='yellow') bottom_frame.pack(side='bottom') bottom_button=Button(bottom_frame,text=' زرار في إطار سفلي' ) bottom_button.pack(padx = 40, pady = 40) main_window.mainloop() وسنحصل على الشكل التالي: نافذة بإطار بحاوية عنوان تطبيق الآلة الحاسبة (الجزء الثاني) سنطبق ما تعلمناه في هذا المقال على تطبيق الآلة الحاسبة، فسنحاول تقسيم النافذة إلى جزئين جزء تعرض فيه المدخلات وهي نتيجة ما يتم النقر عليه، وجزء ثانيٍ وهو جزء الأزرار والعمليات، سنقسم الشاشة إلى إطارين باستخدام الخاصية LabelFrame، الأول للجزء العلوي ونعطيه اسم input_frame و نعنونه بالعنوان "المدخلات"، والآخر للجزء السفلي باسم btns_frame ونعنونه بالعنوان "لوحة الأرقام والعمليات"، سنستخدم هنا نوعين من الإضافة أولًا للإطارات باستخدام الدالة pack ومن ثم باستخدام الشبكة grid لبقية العناصر داخل الإطارات، نضيف هذا الجزء على الشفرة السابقة على النحو التالي: from tkinter import * from ctypes import windll windll.shcore.SetProcessDpiAwareness(1) mycalculator = Tk() mycalculator.title("آلة حاسبة بسيطة") mycalculator.geometry("575x740") mycalculator.resizable(False, False) input_frame=LabelFrame(mycalculator,text="المدخلات",bd=3,width=575) input_frame.pack(side=TOP) btns_frame = LabelFrame(mycalculator,text=" لوحة الأرقام والعمليات ", bg="white",width=575,bd=3) btns_frame.pack() mycalculator.mainloop() حددنا عرض الإطارات بنفس عرض النافذة، و بحدود bd بمقدار عرض 3، وضعنا خلفية الإطار الثاني بلون أبيض. واجهة الآلة الحاسبة الثانية عند تشغيل الشفرة قد لا تبدو مختلفة عن الشفرة السابقة وذلك نتيجة لعدم وضعنا أي عنصر داخل الإطارات فقد لا تبدو حدودها واضحة، سنكمل في المقال التالي تطبيقنا ونضع العناصر داخل النافذة لتظهر لنا الإطارات بصورة واضحة طبعًا بعد التعرف عليها. سنتناول في المقال التالي حاوية العنوان وصناديق المدخلات وهي ما يحتوي عليه الإطار العلوي في نافذة الآلة الحاسبة. المصادر Introduction to Tkinter. Python GUI with Tkinter. Ttk Widgets. Tkinter Pack. Tkinter Grid. Common Widget Properties. How To Position Widgets In Tkinter. Tkinter Frame. Python Tkinter Frame. Python - Tkinter LabelFrame. Introduction to Programming Using Python by Y. Daniel Liang ) Chapter 9 GUI Programming Using Tkinter). Tony Gaddis - Starting Out with Python, Global Edition (2018, Pearson Education),(Chapter 13 GUI Programming). اقرأ أيضًا المقال التالي: حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون المقال السابق: واجهات المستخدم الرسومية في بايثون باستخدام TKinter برمجة الواجهات الرسومية باستخدام Tkinter تعلم البرمجة النسخة العربية الكاملة من كتاب: البرمجة بلغة بايثون
-
يستخدم المبرمج في بداية تعلم البرمجة واجهة سطر الأوامر command-line interface، وهي واجهة تعتمد اعتمادًا كليًا على المدخلات من خلال لوحة المفاتيح، يكون فيها ترتيب الأحداث معتمدًا على طريقة كتابة المبرمج للأوامر ولا رأي للمستخدم في ترتيب سير الأحداث، وعلى العكس من ذلك تكون الواجهات الرسومية Graphical Interface التي يتفاعل فيها المستخدم مع البرنامج من خلال مؤشر الفأرة ويكون المتحكم في سير الأوامر من خلال ما يختار أن ينقر عليه أو أن يقوم بتعبئته من المدخلات بالترتيب الذي يرغبه، فيتفاعل مع العديد من العناصر كالأزرار والقوائم وصناديق المدخلات وغيرها. تقدم لغة البرمجة بايثون العديد من الخيارات لتطوير واجهة المستخدم الرسومية GUI اختصارًا للعبارة Graphical User Interface فعلى سبيل المثال: wxPython وهي أداة مفتوحة المصدر لتطوير الواجهات على عدة منصات مثل ويندوز وماك وغيرهما. JPython وهو تطبيق جافا للبايثون يجمع ما بين قوة التعبير والوضوح. Tkinter وهي مكتبة واجهات رسومية مدمجة مع نسخة بايثون. سنشرح في سلسلة مقالاتنا هذه أساسيات المكتبة Tkinter بالتفصيل. هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة: واجهات المستخدم الرسومية في بايثون باستخدام TKinter. مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون. حاوية العنوان label وصناديق المدخلات Entry في واجهة المستخدم الرسومية في بايثون. الأزرار Buttons ومربعات الرسائل messagebox في واجهة المستخدم الرسومية في بايثون. مربعات الاختيار وأزرار الانتقاء والقوائم في واجهة المستخدم الرسومية في بايثون. Tkinter تعد مكتبة Tkinter -وتنطق T-K-Inter اختصار لكلمة Tk Interface أي واجهات TK- الأشهر والأكثر استخدامًا، ومن حسن الحظ أنها تأتي مدمجة مع لغة البايثون النسخة 3، فلا حاجة لتثبيت أي مكون إضافي لاستخدامها، فهي مكتبة لتطوير الواجهات الرسومية تحوي مجموعة أدوات لعناصر واجهة المستخدم وهي مفتوحة المصدر تستخدمها عدة لغات لتطوير الواجهات لأنظمة ويندوز وماك ويونكس. تعد المكتبة Tkinter في بايثون اختيارًا جيدًا لإنشاء الواجهات الرسومية لعدة أسباب أهمها أنها سهلة التعلم، ويستخدم فيها القليل جدًا من التعليمات البرمجية لإنشاء تطبيق سطح مكتب يعمل بشكل ممتاز، ونستطيع تشغيلها على مختلف أنظمة التشغيل، وكما قلنا مسبقًا لا نحتاج أي مجهودٍ في تثبيتها فهي تأتي مع البايثون بشكل افتراضي. كل هذه المميزات تجعلها نقطة انطلاق قوية للمبتدئين والمتوسطين لتعلم الواجهات الرسومية في البايثون. سنسلط الضوء في هذه السلسلة على المكونات الأساسية في مكتبة Tkinter لصنع واجهة مستخدم رسومية للشفرات البرمجية في بايثون، ونفترض هنا أن القارئ لديه خبرة بأساسيات لغة بايثون لذا ننصحك إن لم يكن لديك خبرة ببايثون بالرجوع إلى سلسلة مقالات المرجع الشامل إلى تعلم لغة بايثون. تعد عملية إنشاء واجهة رسومية باستخدام Tkinter مهمة سهلة تتضمن مجموعة من الخطوات: استيراد الوحدة Tkinter. إنشاء النافذة الرئيسية (التي ستحتوي على جميع العناصر الرسومية). إضافة أي عدد من المكونات التي تحتاجها إلى النافذة الرئيسية. تفعيل دوال الاستجابة لمكوناتك الرسومية. هذه هي ببساطة خطوات إنشاء واجهة رسومية لبرنامج. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن إنشاء أول واجهة رسومية لبرنامجك سنصمم أبسط واجهة رسومية، وهي عبارة عن نافذة تحتوي على عبارة "مرحبًا بواجهات بايثون". الخطوة الأولى هي استدعاء المكتبة Tkinter باستخدام الأمر import ويمكن القيام بذلك بصيغتين مختلفتين import tkinter # أو from tkinter import * هنالك اختلاف طفيف في التعامل مع كل صيغة، سنبدأ باستخدام الصيغة الأولى، فبعد استدعاء المكتبة نحتاج لإنشاء النافذة الرئيسية وذلك بإنشاء كائن object من الصنف TK class، ونختار له اسمًا لنفترض مثلًا سنُطلق عليه النافذة الرئيسية main_window، سيكون الأمر البرمجي بهذا الشكل: import tkinter main_window = tkinter.Tk() عند استخدام الصيغة الأولى من الاستدعاء يُفترض أن تستخدم محتويات المكتبة باستخدام اسم المكتبة في كل مرة model.class وقد تكون الكتابة بهذة الصيغة طويلة قليلًا لذلك يمكننا اختيار اسم مختصر للمكتبة أثناء الاستدعاء واستخدامه بديلًا عن الاسم الأساسي كالتالي: import tkinter as TK main_window = TK.Tk() بعد ذلك نقوم باستدعاء الدالة mainloop والتي تقوم بعمل استمرار لانهائي لظهور النافذة بانتظار بانتظار أن يتفاعل معها المستخدم أو يغلقها، ويكون ذلك بإضافة السطر التالي: import tkinter as TK main_window = TK.Tk() main_window.mainloop() عند تشغيل هذه الشفرة ستظهر لنا نافذة بالشكل التالي: النافذة الرئيسية يمكننا إعادة كتابة الشيفرة باستخدام الصيغة الثانية لاستدعاء المكتبة كالتالي: from tkinter import * main_window = Tk() main_window.mainloop() يستدعي السطر الأول جميع محتويات المكتبة Tkinter من أصناف ودوال وثوابت لتكون من ضمن برنامجك، لذلك نستخدم اسم المصنف فقط دون الحاجة إلى استخدام اسم المكتبة قبل اسم المصنف كما في السابق، وعند تشغيل الشفرة سنحصل على نفس النتيجة للشفرة بالصيغة الأولى. لنقم الآن بإضافة عنصر داخل نافذتنا الرئيسية لنكتب فيه النص المراد إظهاره، لعمل ذلك نحتاج أن ننشئ كائنًا (نختار له اسمًا) من نوع المصنف Label يحتاج هذا الكائن على الأقل إلى تحديد المكان الذي يجب أن يوضع فيه بالإضافة إلى النص الذي تريد كتابته، فتكتب الشفرة على النحو التالي: L=Label(main_window, text="مرحباً بواجهات بايثون ") بعد ذلك نقوم باستخدام الدالة pack والتي تقوم بوضع الكائن على نافذتنا الرئيسية لتكون الشفرة كاملةً على النحو التالي: from tkinter import * main_window = Tk() L=Label(main_window, text="مرحباً بواجهات بايثون ") L.pack() main_window.mainloop() عند تشغيل البرنامج سنحصل على الشكل التالي: نافذة بنص خصائص النافذة الرئيسية هناك الكثير من الخصائص التي يمكن تنسيقها للنافذة لترتيب مظهرها من أبعاد ولون خلفية وحدود ونحوه، الفقرات التالية تشرح أهم الخصائص: عنوان النافذة نضيف عنوانًا لنافذتنا الرئيسية باستخدام الدالة title مع الكائن الذي قمنا بتعريفه لها، بطبيعة الأمر سنقوم بإرسال النص الذي نريد كتابته كعنوان للدالة title ونضيفه إلى الشفرة السابقة في السطر الثالث بهذه الطريقة: from tkinter import * main_window = Tk() main_window.title("أول واجهة رسومية ") L=Label(main_window, text="مرحباً بواجهات بايثون ") L.pack() main_window.mainloop() فنحصل على الشكل التالي: نافذة بعنوان وعلى عكس العملية السابقة بإمكاننا استرجاع عنوان أي نافذة باستخدام القيمة المرجعة من نفس الدالة title ولكن بدون إرسال أي شي لها على النحو التالي: the_title=main_window.title() وبناءً على مثالنا السابق يفترض أن تكون قيمة المتغير the_title هي جملة "أول واجهة رسومية". حجم ومكان ظهور النافذة نتحكم بحجم النافذة وكذلك مكان ظهورها باستخدام الدالة geometry وفيها نحتاج لتحديد الطول والعرض بالبكسل، وكذلك الإحداثي السيني والصادي للمكان المراد ظهور النافذة فيه في شاشة العرض، ويوضح الشكل التالي التفاصيل بالنسبة للشاشة: احداثيات النافذة الطريقة العامة لاستخدام الدالة على النحو التالي: main_window.geometry(‘WidthxLength+x(horizontal)+y(vertical)’) يجب مراعاة أن التفاصيل تعطى على صيغة سلسلة نصية أي أنها محاطة بعلامات التنصيص. لنحدد طولًا وعرضًا لنافذتنا السابقة، لنفرض أننا نرغب أن تكون بشكل مربع بطول وعرض 400 بكسل، وأن تظهر مبتعدة عن الجانب الأيسر من الشاشة بمقدار 200 بكسل ومن أعلى الشاشة بمقدار 300 بكسل فتكتب الشفرة على النحو التالي: main_window.geometry('400x400+200+300') لنفترض أنك تريد أن تُظهر نافذة برنامجك في وسط الشاشة تمامًا، لفعل ذلك تحتاج أن تحصل على طول وعرض شاشة العرض في جهاز الحاسوب لتحقيق ذلك نستخدم الدالة winfo_screenwidth للحصول على عرض الشاشة، والدالة winfo_screenheight لنحصل على طولها، يتم استدعائها باستخدام النافذة الرئيسية على النحو التالي: screen_width = main_window.winfo_screenwidth() screen_height = main_window.winfo_screenheight() للحصول على إحداثيات نقطة منتصف الشاشة نقسم الطول والعرض على 2، فنحصل على النقطة (ارتفاع الشاشة/2 ،عرض الشاشة/2)، وعند كتابة هذه النقطة في الدالة سيكون موضع ظهور النافذة في الجزء السفلي الأيمن من الشاشة، حيث أن بداية رسم النافذة يكون من النقطة العلوية اليسرى، الشكل التالي يوضح المقصود: موضع النافذة في الشاشة لذلك سنقوم بوضع منتصف نافذتنا الرئيسية في منتصف شاشة العرض الأساسية فتكون الصياغة العامة للإحداثي السيني على النحو التالي: main_window.winfo_screenwidth()//2 - main_window_width//2 قمنا باستخدام القسمة الصحيحة للحصول على عددٍ صحيح كامل بلا فواصل، وعلى نفس النهج نحصل على الإحداثي الصادي. يجب مراعاة أن المتغيرات التي أنشئت لحساب الإحداثيات عددية النوع بينما الدالة geometry تأخذ سلسلة نصية لذلك أضفنا تنسيق لنحول الأعداد إلى نص. سنُظهر الآن نافذتنا ذات الأبعاد 400*400 بكسل طولًا وعرضًا في منتصف الشاشة، فتكون الشفرة كاملة على النحو التالي: from tkinter import * main_window = Tk() main_window.title("أول واجهة رسومية ") screen_width = main_window.winfo_screenwidth() screen_height = main_window.winfo_screenheight() middle_width= screen_width //2 - 400//2 middle_hight= screen_height//2 - 400//2 main_window.geometry(f'400x400+{middle_width}+{middle_hight}') L=Label(main_window, text="مرحباً بواجهات بايثون ") L.pack() main_window.mainloop() ويظهر الشكل التالي نتيجة الشفرة عند تشغيلها: موضع النافذة في الشاشة التعديل على حجم النافذة يُسمح للمستخدم بشكل افتراضي أن يقوم بتعديل حجم النافذة (الطول والعرض) باستخدام الفأرة، وتستطيع أن تمنع ذلك باستخدام الدالة resizable(width,height)، حيث نعطيها قيمة خطأ False لكلٍ من الطول والعرض فيمنع ذلك تعديلهم من المستخدم، تكتب كما يلي: main_window.resizable(False, False) بإمكانك ترك النافذة كما في الإعدادات الإفتراضية قابلة للتعديل ويمكنك أن تضبط .. أقصى طول وعرض تسمح للنافذة أن تتوسع له وأقل طول وعرض يمكن أن تنكمش له باستخدام الدالتين maxsize و minsize على النحو التالي: main_window.minsize(min_width, min_height) main_window.maxsize(min_height, max_height) تغيير نوع وحجم خط عناصر النافذة نستطيع تغيير خط العناصر على النافذة الرئيسية باستخدام الدالة option_add، ونعطيها نوع الخط وحجم الخط الذي نرغب بعرضه وسيطبق على جميع العناصر التي توضع على النافذة، لنحدد حجم الخط 20 ونوعه Times مثلًا سنكتب السطر التالي: main_window.option_add('*Font', 'Times 20') وتكون النتيجة: نوع وحجم خط النافذة للحصول على قائمة بأسماء الخطوط المتوفرة بإمكاننا تشغيل الشفرة التالية وسيخرج لنا قائمة بالخطوط: from tkinter import Tk, font root = Tk() print(font.families()) شفافية النافذة تسمح مكتبة Tkinter للمستخدم بالتحكم بشفافية النافذة الرئيسية باستخدام الخاصية ألفا alpha وإعطائها قيمة تتراوح ما بين 0.0 (شفافة بالكامل) إلى 1.0 (معتم بالكامل)، السطر التالي يجعل النافذة الرئيسية شفافة بنسبة 50%: main_window.attributes('-alpha',0.5) شفافية النافذة تحسين دقة النافذة من شكل النافذة السابق قد تبدو لك جملة (مرحباً بواجهات بايثون) ضبابية قليلًا وأقل وضوحًا من عنوان النافذة، لنحسن دقة عناصر النافذة نضيف لبرنامجنا أسطر الشيفرة التالية: from ctypes import windll windll.shcore.SetProcessDpiAwareness(1) فنحصل على النتيجة في الشكل التالي: دقة النافذة ويتضح هنا أن دقة النص تحسنت بشكل ملحوظ، ولكن يجب الأخذ بعين الاعتبار هنا أن استخدامك لهذه الأسطر البرمجية سيؤثر على حجم النافذة الرئيسية، فيجب الانتباه لذلك ووضع قياسات مناسبة للحجم الذي تريد استخدامه. تطبيق الآلة الحاسبة (الجزء الأول) سنعمل خلال هذه السلسة من الدروس بتطبيق ما تعلمناه مباشرةً من خلال إنشاء آلة حاسبة بسيطة باستخدام الواجهات الرسومية، و ننفذها على عدة أجزاء في كل درس باستخدام ما تم شرحه فيه. نحتاج في البداية لتخيل شكل الآلة، فهي عبارة عن نافذة تحتوي مجموعة من الأزرار جزء منها للأرقام وجزء للعمليات، ومكان لإظهار النتائج، مرتبة بشكل يشبه الآلة الحاسبة الاعتيادية، ستبدو واجهتنا على النحو التالي: واجهة الآلة الحاسبة سنبدأ برسم النافذة من خلال ما تعلمنا في درس اليوم، فنبدأ باستدعاء مكتبة tkinter ونرسم النافذة بحدود تقريبية بما نراه يتناسب مع حجم النافذة المطلوب (قد نضطر لتعديله لاحقًا بعد وضع العناصر)، نستخدم الدالة geometry بحدود 575 عرض و طول 740، ونضع عنوانًا باستخدام الخاصية title فنكتب (آلة حاسبة بسيطة)، يجب أن لا ننسى استخدام جزء الشفرة الذي يحافظ على دقة محتويات النافذة، ونثبت مقياس النافذة باستخدام الخاصية resizable، فيصبح محتوى شيفرتنا على النحو التالي: from tkinter import * from ctypes import windll windll.shcore.SetProcessDpiAwareness(1) mycalculator = Tk() mycalculator.title("آلة حاسبة بسيطة") mycalculator.geometry("575x740") mycalculator.resizable(False, False) mycalculator.mainloop() ونحصل على النافذة التالية: واجهة الآلة الحاسبة الأولى في المقال القادم، سنتكلم عن ماهية العناصر التي توضع على النافذة، وكيفية وضعها وترتيبها عليها، ونطبق ما سنتعلمه على آلتنا الحاسبة. المصادر Python GUI Examples (Tkinter Tutorial) - Like Geeks An Essential Guide to Tkinter Window Tkinter Hello, World! How to improve Tkinter window resolution - CodersLegacy How to change font type and size in Tkinter? - CodersLegacy Python - GUI Programming (Tkinter) Introduction to Programming Using Python by Y. Daniel Liang Tony Gaddis - Starting Out with Python, Global Edition (2018, Pearson Education). اقرأ أيضًا المقال التالي: مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون برمجة الواجهات الرسومية باستخدام Tkinter تعلم البرمجة تعرف على أبرز مميزات لغة بايثون النسخة العربية الكاملة من كتاب: البرمجة بلغة بايثون