اذهب إلى المحتوى

مدخل إلى عناصر واجهات المستخدم الرسومية Widgets في بايثون


Nouf_mohamad

تحدثنا في المقال السابق عن الواجهات الرسومية للتطبيقات باستخدام TKinter، وتطرقنا للنافذة الرئيسية التي هي أساس أي تطبيق مكتوب باستخدام الواجهات وشرحنا مجموعة من خصائصها، سنكمل في هذا المقال ونتحدث عن العناصر التي نضعها على النافذة الرئيسية، والتي يطلق عليها مسمى Widgets.

هذه المقالة جزء من سلسلة مقالات تشرح أساسيات مكتبة TKinter لبناء واجهات رسومية في بايثون، وإليك فهرس السلسلة كاملة:

Widgets

هي عبارة عن عناصر التحكم التي نضعها على النافذة ليتمكن المستخدم من التفاعل معها، حيث توضح له معنى أو تطلب منه أدخال أمر معين أو تأخذ منه أمرًا لتنفيذ مهمة مطلوبة مثل الأزرار، ومربعات الإدخال وحاويات العناوين ومربعات الإختيار والقوائم وغيرها، الجدول التالي يوضح مجموعة من أهم العناصر التي يمكننا إضافتها على النافذة:

اسم العنصر   الوصف
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()

ستبدو المخرجات عند تشغيل الشيفرة بالشكل التالي:

001_GUI2_Classic_Themed_Widgets.jpg

الطريقة الحديثة والكلاسيكية لعناصر واجهات المستخدم

قد لا يبدو الاختلاف بينهما واضحًا، لكن كما سبق وقلنا يعتمد المظهر كثيرًا على نوع نظام التشغيل الذي تعمل عليه.

التحكم بخصائص العناصر

جميع هذه العناصر لها مجموعة متنوعة من الخصائص بخيارات مختلفة، تختلف باختلاف العناصر حسب ما يتميز به كل عنصر، كما توجد خصائص مشتركة بين غالبية العناصر مثل: لون الخلفية، ولون الخلفية عندما يكون العنصر فعالًا، والنص المكتوب، ولون النص ونوع الخط، ولون النص عندما يكون العنصر فعالًا، والعرض والارتفاع بالبكسل، وشكل المؤشر …إلخ. ويُسمح لنا بالتحكم فيها من خلال 3 طرق إما في وقت الإنشاء من خلال معاملات الدوال أو بعد إنشاء العنصر من خلال استخدام القواميس أو الدالة config:

1. في وقت الإنشاء من خلال معاملات الدوال keyword arguments

وهذه هي الطريقة التي استخدمناها حتى الآن لوضع نص في حاوية العنوان أو في الزر كما في المثال السابق بتحديد اسم معامل الدالة بنوع الخاصية المطلوبة وهي text ومن ثم إعطائه قيمة النص المطلوبة أو مثلًا خاصية لون الخط foreground ونضعه مثلًا أزرق blue.

L=Label(main_window, text='نص باللون الأزرق' ,foreground='blue')

سيبدو الشكل على النحو التالي :

002_GUI2_creation_time.jpg

إضافة خصائص وقت الإنشاء

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 سنحصل على النتائج التالية:

003_GUI2_pack.jpg

استخدام الدالة 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()

فنحصل على الشكل التالي:

004_GUI2_pad_ipad.jpg

استخدام الخاصية 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()

ونحصل على النتيجة التالية:

005_GUI2_place.jpg

استخدام الدالة 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()

عند تشغيل الشفرة نحصل على التالي:

006_GUI2_frame.jpg

نافذة بإطار

كما قلنا سابقًا، الهدف الأساسي من الإطارات تنظيم النافذة، سنقوم برسم نافذة تحتوي على عدة إطارات في كل اتجاه، و سنوزع العناصر فيها على النحو التالي:

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()

وسنحصل على الشكل التالي:

007_GUI2_colored_frame.jpg

نافذة بإطارات ملونة

الإطارات بحاوية عنوان 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()

وسنحصل على الشكل التالي:

008_GUI2_Labelframe.jpg

نافذة بإطار بحاوية عنوان

تطبيق الآلة الحاسبة (الجزء الثاني)

سنطبق ما تعلمناه في هذا المقال على تطبيق الآلة الحاسبة، فسنحاول تقسيم النافذة إلى جزئين جزء تعرض فيه المدخلات وهي نتيجة ما يتم النقر عليه، وجزء ثانيٍ وهو جزء الأزرار والعمليات، سنقسم الشاشة إلى إطارين باستخدام الخاصية 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، وضعنا خلفية الإطار الثاني بلون أبيض.

009_GUI2_calculator_1.jpg

واجهة الآلة الحاسبة الثانية

عند تشغيل الشفرة قد لا تبدو مختلفة عن الشفرة السابقة وذلك نتيجة لعدم وضعنا أي عنصر داخل الإطارات فقد لا تبدو حدودها واضحة، سنكمل في المقال التالي تطبيقنا ونضع العناصر داخل النافذة لتظهر لنا الإطارات بصورة واضحة طبعًا بعد التعرف عليها.

سنتناول في المقال التالي حاوية العنوان وصناديق المدخلات وهي ما يحتوي عليه الإطار العلوي في نافذة الآلة الحاسبة.

المصادر

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...