بناء الـواجـهـات الـرسـومـية بـرمـجـيـاً

في هذا القسم ...
"إنشاء الـ GUI "
"أهم التوابع المستخدمة"
"إنشاء ملف Matlab لواجهة المستخدم الرسومية"
"تخطيط GUI "
"إضافة المكونات"
"تهيئة واجهة المستخدم الرسومية "
"برمجة واجهة المستخدم الرسومية GUI "
تنفيذ واجهة المستخدم الرسومية النهائية "

إنشاء GUI :
نوضح فيما يلي كيف يمكنك كتابة البرنامج النصي الذي ينشئ واجهة المستخدم GUI الموضحة في الشكل المبين .

إن كافة الكائنات الموجودة في البرنامج المبينة تم التعرف عليها في الدرس الأول , إن واجهة المثال تتضمن :
-         جملة محاور axes.
-         قائمة منبثقة pop-up menu تسرد مجموعات مختلفة من المعطيات و التي تقابل توابع في MATLABهي sine , membrane , peaks.
-         نص استاتيكي من أجل وضع تسمية للقائمة المنبثقة.
-         ثلاثة أزرار ضغط تعطي ثلاثة أنواع مختلفة من الأشكال contour , mesh , surface.
من أجل استخدام هذا المثال (GUI) فإن المستخدم يختار مجموعة من المعطيات من القائمة المنبثقة , وعندها فإنه ينقر أحد من أزرار ضغط نوع الرسم , إن النقر على الزر يشمل تنفيذ الاستدعاء الذي يرسم المعطيات المختارة ضمن جملة المحاور.

أهم التوابع المستخدمة :
يوفر برنامج الماتلاب مجموعة من التوابع لإنشاء وبناء واجهات المستخدم الرسومية. يوضح الجدول التالي أهم التوابع التي تحتاجها لبناء المثال المدروس.
الـتـابـع
الـوصـف
Align
يحاذي محاور و عناصر التحكم لواجهة المستخدم
Axes
ينشئ عناصر محاور
Figure
ينشئ عناصر الشكل حيث أن GUI هي عنصر شكل
Movegui
يحرك شكل GUI إلى مكان محدد على الشاشة
Uicontrol
ينشئ عناصر التحكم بواجهة المستخدم مثل أزرار الضغط , نص ستاتيكي , و لقوائم المنبثقة

إنـشـاء مـلـف ماتلاب لواجهة المستخدم الرسومية:

ابدأ بإنشاء و بناء ملف M-file للواجهة المدروسة .
1.    على موجه MATLAB , اكتب edit فيقوم الماتلاب بفتح المحرر.
2.    اكتب التعليمات التالية. تعليمة التابع هذه هي السطر الأول من الملف function simple_gui .
3.    أضف هذه التعليقات إلى ملف MATLABبعد تعليمة التابع. سوف تُعرض هذه التعليقات في سطر الأمر استجابة للأمر help. و يجب أن تتبع بسطر فارغ.
functionsimple_gui_test
% SIMPLE_GUI Select a data set from the pop-up menu, then
% click one of the plot-type push buttons. clicking the button
% plots the selected data in the axes
end
نحتاج هنا لكتابة التعلمية end  بسبب أن المثال مكتوب باستخدام التوابع المتداخلة (nested functions).
4.    خزن الملف على مجلدك الحالي أو في المكان الذي فيه مسار ملفات MATLAB الخاصة بك. الخطوة التالية ستكون تخطيط الواجهة GUIالبسيطة .

تخطيط GUI :
كان التعريف السابق لقيمة المتغير Position بطريقة بدائية . لأنه لم يكن هناك أخذ بعين الاعتبار لحجم الشاشة المتغير من حاسوب لآخر , ولتجاوز هذا الإشكال يمكننا إستغلال المتغير ScreenSize
الوظيفة
الخاصية
تعديل لون الواجهة
Color
إبقاء أو حذف شريط المهام
Menubar
تسمية الواجهة الرسومية
Name
تعديل ترقيم الواجهة
Numbertitle
تحديد الواجهة الأم
Parent
تحديد المكان و المقاييس
Position
صلاحية تعديل حجم الشاشة
Resize
تحديد المؤشر
Tag
إبقاء أو حذف شريط الأدوات
Toolbar
بيانات المستخدم
Userdata
إظهار أو إخفاء الواجهة
Visible

إضافة المكونات :
الـخـاصـيـة
الـوصـف
Style
في المثال , pushbutton تحدد المكون كزر ضغط
String
نحدد الاسم الذي سيظهر على كل زر ضغط.
Position
تستخدم شعاع رباعي العناصر لتحديد مكان كل زر ضغط ضمن GUI وقياسه , و الواحدات الافتراضية هي البيكسل.
Parent
تحديد الواجهة الأم
Backgroundcolor
تحديد لون الخلفية
Tag
تحديد المؤشر
FontWeight
تحديد نوع الكتابة
Callback
الاستدعاء , تحديد اسم الدالة التي نريد استدعائها لتنفيذ السطور البرمجية المطلوبة عن الضغط على الكائن
Interruptible
التعطيل , توفر إمكانية تعطيل الوظيفة المسندة للمكون , كما يوحي إسمها.
Value
تحديد القيمة
يتم تخطيط واجهة المستخدم الرسومية على مرحلتين :
-         بناء الشكل .
-         إضافة المكونات.
-         بناء الشكل (تـصـمـيـم الـواجـهـة) :في برنامج الماتلاب , فإن الواجهة عبارة عن شكل. و بالتالي فإن الخطوة الأولى هي أن تنشئ الشكل و نوضعه على الشاشة. إنها أيضاً تجعل GUI غير مرئية و لذا فإن مستخدم GUI لا يستطيع أن يرى المكونات المضافة أو المهيأة. عندما يتم إضافة جميع المكونات على الواجهة و تكون مهيأة , فإن المثال سيجعلها مرئية.
% Initialize and hide the GUI as it is being consructed.
f=figure('Visible','off','Position',[360,500,450,285]);
و يمكن تغيير لون خلفية الواجهة بكتابة :
f=figure('Visible','off','Position',[360,500,450,285],'Color',[0.1 0.2 0.6]);
لو أردنا وضع أسماء نختارها نحن لتكون مناسبة أكثر لمحتوى الواجهة الرسومية أو لتحمل اسم التطبيق , يمكن ببساطة كتابة :
f=figure('Visible','off','Position',[360,500,450,285],'Color',[0.1 0.2 0.6],'Name','Demo Design');
لو أردنا التخلص من التسمية التلقائية التي تضيفها الواجهة نكتب و ببساطة :
f=figure('Visible','off','Position',[360,500,450,285],'Color',[0.1 0.2 0.6],'Name','Demo Design','NumberTitle','off');
وبالنتيجة نحصل على الواجهة :
لو أردنا تعطيل صلاحية تغيير حجم الشاشة نكتب :
f=figure('Visible','off','Position',[360,500,450,285],'Color',[0.1 0.2 0.6],'Name','Demo Design','NumberTitle','off','Resize','off');
والغاية من ذلك الحفاظ على توزع العناصر المكونة للواجهة و عدم إنحصارها في ركن واحد عند تكبيرها. يمكن أن تحدث هذه المشاكل عندما تكون الإحداثيات المسندة للمكونات ثابتة و مستقلة عن حجم الواجهة الذي تحدده قيمة المتغير ScreenSize.
SCREENSIZE=get(0,'ScreenSize')
f=figure('Visible','off','Position',[SCREENSIZE(1) SCREENSIZE(2) SCREENSIZE(3) SCREENSIZE(4)],'Color',[0.1 0.2 0.6],'Name','Demo Design','NumberTitle','off','Resize','off');

إن طلب تابع figure يستخدم زوجي قيمة/خاصية property/value. إن خاصية Position عبارة عن شعاع رباعي العناصر (4-element) يحدد مكان GUI على الشاشة و أبعادها : ]المسافة من اليسار , المسافة من الأسفل , الارتفاع, العرض[. الواحدات الافتراضية هي البيكسل pixels.
ويمكن للمبرمج إضافة عدة تعديلات أخرى على الواجهة الرسومية عبر إدراج خاصيات أخرى. و يبين الجدول التالي أهم الخصائص و وظيفة كل منها .
يضم المثال المدروس لواجهة GUI ستة مكونات : ثلاثة أزرار ضغط , نص ستاتيكي واحد , وقائمة منبثقة واحدة , وجملة محاور واحدة. لنبدأ بكتابة التعليمات التي تضيف هذه المكونات إلى GUI. إن إنشاء أزرار الضغط , النص الستاتيكي, القائمة المنبثقة يتم بالتابع uicontrol. أما إنشاء المحاور فيتم من خلال التابع axes.
1.     أضف أزرار الضغط الثلاثة إلى واجهتك بإضافة هذه التعليمات إلى الملف M-fileوذلك بعد طلب التابع figure.
% Construct the components.
hsurf = uicontrol('style','pushbutton','String','Surf','Position',[315,220,70,25]);
hmesh = uicontrol('style','pushbutton','String','Mesh','Position',[315,180,70,25]);
hcontour = uicontrol('style','pushbutton','String','countour','Position',[315,135,70,25]);

تستخدم هذه التعليمات التابع uicontrol لإنشاء أزرار الضغط. كل تعليمة تستخدم سلسلة من الأزواج قيمة/خاصية propert/valueلتعريف زر الضغط. ويوضح الجدول و يصف أهم الخصائص مع العلم أنه في كل طلب يتم استرجاع مقبض المكونة التي تم إنشاؤها.
2.    أضف القائمة المنبثقة و عنوانها إلى واجهتك بإضافة هذه التعليمات إلى الملف M-file و ذلك بعد تعريفات زر الضغط.
hpopup=uicontrol('style','popupmenu','String',{'Peaks','Membrane','Sine'},'Position',[300,50,100,25]);
htext=uicontrol('style','text','String','Select Data','Position',[325,90,60,15]);

من أجل القائمة المنبثقة فإن خاصية String تستخدم مصفوفة خلية لتحدد الأجزاء الثلاثة من القائمة المنبثقة : Sinc , Membrane , Peaks . أما بالنسبة للنص الستاتيكي فإنه يستخدم لعنونة القائمة المنبثقة. إن خاصية String لهذا النص تخبر مستخدم GUI ليختار معطيات Select Data. الوحدات الافتراضية لهذه المكونات هي البيكسل.
3.    أضف المحاور إلى GUIوذلك بإضافة التعليمة التالية إلى الملف M-file. اضبط خاصية Units على البيكسل بحيث انها تملك نفس واحدات المكونات الاخرى.
ha=axes('Units' , 'pixels' , 'Position',[50,60,200,185]);
4.    حاذي جميع المكونات ما عدا المحاور حول مركزها وذلك بالتعليمة التالية , أضفها إلى الملف M-file بعد كل تعريفات المكونات :
align([hsurf,hmesh,hcontour,htext,hpopup],'Center','None');
5.    اجعل واجهتك GUIمرئية هذا الأمر بعد أمر المحاذاة :
set(f,'Visible','on')
6.    بهذا الشكل سيكون ملف M-file كما يلي :

functionsimple_gui
% SIMPLE_GUI Select a data set from the pop-up menu, then
% click one of the plot-type push buttons. clicking the button
% plots the selected data in the axes

% Initialize and hide the GUI as it is being consructed.
f=figure('Visible','off','Position',[360,500,450,285]);

% Construct the components.
hsurf = uicontrol('style','pushbutton','String','Surf','Position',[315,220,70,25]);
hmesh = uicontrol('style','pushbutton','String','Mesh','Position',[315,180,70,25]);
hcontour = uicontrol('style','pushbutton','String','countour','Position',[315,135,70,25]);

hpopup=uicontrol('style','popupmenu','String',{'Peaks','Membrane','Sine'},'Position',[300,50,100,25]);
htext=uicontrol('style','text','String','Select Data','Position',[325,90,60,15]);

ha=axes('Units' , 'pixels' , 'Position',[50,60,200,185]);
align([hsurf,hmesh,hcontour,htext,hpopup],'Center','None');

set(f,'Visible','on')
end


تهيئة واجهات المستخدم الرسومية GUI :

عندما نجعل واجهتك مرئية Visible , فإنها يجب أن تهيأ بحيث تكون جاهزة للمستخدم. سنوضح فيما يلي كيف يمكن :
1.    بناء (تصميم) الواجهة الرسومية بحيث تبدو أو تظهر بشكل لائق عندما يضبط قياسها بتغيير واحدات الشكل  و المكونة إلى normalized. يؤدي ذلك إلى إعادة ضبط قياس المكونات وجعلها متناسبة مع بعضها عند تغيير ضبط قياس الواجهة GUI. إن الواحدات normalized تعطي الزاوية اليسارية السفلى لنافذة الشكل القيمة (0,0) والزاوية اليمينية العلوية القيمة (1,1).
2.    توليد المعطيات للرسم. إن المثال يحتاج ثلاث مجموعات من المعطيات peaks_data , sinc_data , membrane_data. كل مجموعة من هذه المجموعات تقابل أحد أجزاء القائمة المنبثقة.
3.    إنشاء الرسم الأولي على المحاور.
4.    تخصيص اسم الواجهة الذي سيظهر على عنوان النافذة.
5.    تحريك الواجهة الرسومية إلى مركز الشاشة.
6.    جعل الواجهة الرسومية مرئية.

أ‌)       نستبدل الشيفرة التالية في ملف (M-file) :
% Make the GUI visible
set(f,'Visible','on')
     بهذه الشيفرة :
% Initialize the GUI
% Change units to normalized so components resize automatically.
set([f,hsurf,hmesh,hcontour,htext,hpopup],'Units','normalized');
% Generate the data to plot.
peaks_data=peaks(35);
membrane_data=membrane;
[x,y]=meshgrid(-8:.5:8);
r=sqrt(x.^2+y.^2);+eps;
sinc_data=sin(r)./r;
% Create a plot in the axes.
current_data=peaks_data;
surf(current_data);
% Assign the GUI a name to appear in the window title.
set(f,'Name','Simple GUI')
% Move the GUI to the center of the screen
movegui(f,'center')
% Make the GUI visible
set(f,'Visible','on')
ب‌)  وبالتالي سيبدوا الملف M-fileالخاص بواجهتك كما يلي :
function simple_gui
% SIMPLE_GUI Select a data set from the pop-up menu, then
% click one of the plot-type push buttons. clicking the button
% plots the selected data in the axes

% Initialize and hide the GUI as it is being consructed.
SCREENSIZE=get(0,'ScreenSize')
f=figure('Visible','off','Position',[360,500,450,285]);

% Construct the components.
hsurf = uicontrol('style','pushbutton','String','Surf','Position',[315,220,70,25]);
hmesh = uicontrol('style','pushbutton','String','Mesh','Position',[315,180,70,25]);
hcontour = uicontrol('style','pushbutton','String','countour','Position',[315,135,70,25]);

hpopup=uicontrol('style','popupmenu','String',{'Peaks','Membrane','Sinc'},'Position',[300,50,100,25]);
htext=uicontrol('style','text','String','Select Data','Position',[325,90,60,15]);

ha=axes('Units' , 'pixels' , 'Position',[50,60,200,185]);

align([hsurf,hmesh,hcontour,htext,hpopup],'Center','None');

% Initialize the GUI
% Change units to normalized so components resize automatically.
set([f,hsurf,hmesh,hcontour,htext,hpopup],'Units','normalized');
% Generate the data to plot.
peaks_data=peaks(35);
membrane_data=membrane;
[x,y]=meshgrid(-8:.5:8);
r=sqrt(x.^2+y.^2);
     sinc_data=sin(r)./r;
% Create a plot in the axes.
current_data=peaks_data;
surf(current_data);
% Assign the GUI a name to appear in the window title.
set(f,'Name','Simple GUI')
% Move the GUI to the center of the screen
movegui(f,'center')
% Make the GUI visible
set(f,'Visible','on')
end
جـ) قم بتنفيذ برنامجك النصي عن طريق كتابة simple_gui على سطر الأوامر , وبالتالي ستظهر واجهتك كما يلي.

برمجة واجهة المستخدم الرسومية GUI :
إنك ستستخدم استدعاءات لتبرمج مكونات GUI. إن الاستدعاءات عبارة عن توابع يتم تنفيذها بالتجاوب مع الأحداث المولدة من قبل المستخدم مثل نقر الفأرة مثلاً. نوضح فيما يلي كيف يمكن كتابة الاستدعاءات من أول واجهة بسيطة , و بعدها نبين كيف يمكن ربط كل استدعاء مع مكونته.
-         برمجة القائمة المنبثقة في الواجهة الرسومية
إن القائمة المنبثقة تمكن المستخدمين من اختيار المعطيات التي سترسم. عندما يقوم مستخدم GUIباختيار أحد المجموعات الثلاثة من المعطيات , فإن MATLAB يضبط خاصية Value للقائمة المنبثقة بالدليل المقابل للعبارة النصية المختارة. عندها فإن استدعاء القائمة المنبثقة يقرأ خاصية Value لهذه القائمة ليحدد ما هو الجزء الذي يجب عرضه حالياً و يضبط Current_dataتبعاً لذلك. 

أضف الاستدعاء التالي إلى ملفك بعد شيفرة التهيئة و قبل تعليمة end النهائية.
% Pop-up menu callback. Read the pop-up menu Value property
% to determine which item is currently displayed and make it
% the current data. This callback automatically has access to
% current data because this function is nested at a lower level.
    functionpopup_menu_Callback(source,eventdata)
        %Determine the selected data set.
        str=get(sourse,'string');
        val=get(source,'Value');
        % Set current data to the selected data set.
        switch str{val}
            case 'Peaks' %User selects Peaks
                current_data=peaks_data;
            case 'Membrane' %User selects Membrane
                current_data=membrane_data;
            case 'Sinc'  % User selects Sinc
                current_data=sinc_data;
        end
    end
-         برمجة ازرار الضغط في الواجهة الرسومية
ينشئ كل من أزرار الضغط الثلاثة نوعاً من الرسم باستخدام المعطيات المحددة من الاختيار الحالي في القائمة المنبثقة. إن استدعاءات زر الضغط ترسم المعطيات الموجودة في current_data. إنها و بشكل أوتوماتيكي تدخل إلى Current_data بسبب أنها متداخلة عند مستوى منخفض.
أضف الاستدعاءات التالية إلى ملف MATLAB الخاص بك بعد استدعاء القائمة المنبثقة و قبل تعليمة endالنهائية :
% Push button callbacks. Each callback plots current_data in the
% specified plot type.

    functionsurfbutton_Callback(source,eventdata)
        % Display surf plot of the currently selected data.
        surf(current_data)
    end

    function meshbutton_Callback(source,eventdata)
        % Display mesh plot of the currently selected data.
        mesh(current_data)
    end

    functioncontourbutton_Callback(source,eventdata)
        % Display contour plot of the currently selected data.
        contour(current_data)
    end

-         ربط الاستدعاءات مع مكوناتها
عندما يقوم مستخدم الواجهة الرسومية باختيار مجموعة المعطيات من القائمة المنبثقة أو ينقر على أحد أزرار الضغط , فإن MATLABينفذ الاستدعاء المرافق مع هذا الحدث الجزئي. و لكن كيف يعرفMATLAB  ماهو الاستدعاء الذي سينفذ ؟ من أجل ذلك يجب عليك أن تستخدم خاصية callbackللمكونات لتحديد اسم الاستدعاء الذي يترافق مع المكونة.

1.    لتعليمة uicontrol التي تعرف زر الضغط Surf, أضف زوج قيمة/خاصية property/value التالي :
'Callback',{@surfbutton_Callback}
إن الاستدعاء Callback هو اسم الخاصية , بينما Surfbutton_callback هو اسم الاستدعاء الذي يخدم في زر الضغط Surf.

2.    بشكل مشابه , بالنسبة للتعليمة uicontrol التي تعرف القائمة المنبثقة أضف زوج قائمة/خاصية كمايلي :
'Callback',{@popup_menu_Callback}

تنفيذ واجهة المستخدم الرسومية النهائية :
من خلال الفقرات السابقة قمت ببناء واجهة بسيطة , و فيما يلي نبين الملف M-file  النهائي و كيفية تنفيذ الواجهة الرسومية. طبعاً الآن أصبح لديك برنامج M-fileموضح بالتعليمات التالية :
functionsimple_gui
% SIMPLE_GUI Select a data set from the pop-up menu, then
% click one of the plot-type push buttons. clicking the button
% plots the selected data in the axes

% Initialize and hide the GUI as it is being consructed.
SCREENSIZE=get(0,'ScreenSize')
f=figure('Visible','off','Position',[360,500,450,285]);

% Construct the components.
hsurf = uicontrol('style','pushbutton','String','Surf','Position',[315,220,70,25],'Callback',{@surfbutton_Callback});
hmesh = uicontrol('style','pushbutton','String','Mesh','Position',[315,180,70,25],'Callback',{@meshbutton_Callback});
hcontour = uicontrol('style','pushbutton','String','countour','Position',[315,135,70,25],'Callback',{@contourbutton_Callback});

hpopup=uicontrol('style','popupmenu','String',{'Peaks','Membrane','Sinc'},'Position',[300,50,100,25],'Callback',{@popup_menu_Callback});
htext=uicontrol('style','text','String','Select Data','Position',[325,90,60,15]);

ha=axes('Units' , 'pixels' , 'Position',[50,60,200,185]);

align([hsurf,hmesh,hcontour,htext,hpopup],'Center','None');

% Initialize the GUI
% Change units to normalized so components resize automatically.
set([f,hsurf,hmesh,hcontour,htext,hpopup],'Units','normalized');
% Generate the data to plot.
peaks_data=peaks(35);
membrane_data=membrane;
[x,y]=meshgrid(-8:.5:8);
r=sqrt(x.^2+y.^2);
sinc_data=sin(r)./r;
% Create a plot in the axes.
current_data=peaks_data;
surf(current_data);
% Assign the GUI a name to appear in the window title.
set(f,'Name','Simple GUI')
% Move the GUI to the center of the screen
movegui(f,'center')
% Make the GUI visible
set(f,'Visible','on')

% Pop-up menu callback. Read the pop-up menu Value property
% to determine which item is currently displayed and make it
% the current data. This callback automatically has access to
% current data because this function is nested at a lower level.
   
    functionpopup_menu_Callback(source,eventdata)
        %Determine the selected data set.
        str=get(source,'string');
        val=get(source,'Value');
        % Set current data to the selected data set.
        switch str{val}
            case 'Peaks' %User selects Peaks
                current_data = peaks_data;
            case 'Membrane' %User selects Membrane
                current_data = membrane_data;
            case 'Sinc'  % User selects Sinc
                current_data = sinc_data;
        end
    end

% Push button callbacks. Each callback plots current_data in the
% specified plot type.

    functionsurfbutton_Callback(source,eventdata)
        % Display surf plot of the currently selected data.
        surf(current_data)
    end

    functionmeshbutton_Callback(source,eventdata)
        % Display mesh plot of the currently selected data.
        mesh(current_data)
    end

    functioncontourbutton_Callback(source,eventdata)
        % Display contour plot of the currently selected data.
        contour(current_data)
    end
end
من أجل تنفيذ الواجهة الرسومية قم بالخطوات التالية :
1.    نفذ الواجهة الرسومية البسيطة بكتابة اسم ملف M-file على سطر الأوامر
Simple_gui
ستظهر لك الواجهة الموضحة فيما يلي . . .
2.    في القائمة المنبثقة , اختر Membraneو انقر على الزر Mesh. ستظهر لك الواجهة رسم شعار MATLABمن النوع Mesh كما هو موضح.
3.    قم بتنفيذ كل الخيارات الاخرى الممكنة قبل إغلاق الواجهة GUI.