![]() |
8. Interfaces-utilisateur graphiques (GUI)Ce chapitre est dédié à Danièle ♥ 28.4.2016 ☆ |
![]() |
MATLAB ainsi qu'Octave GUI (pour ce dernier depuis la version 4) offrent la possibilité de programmer avec beaucoup de facilité, au-dessus des applications que l'on développe, de véritables interfaces-utilisateur graphiques (GUI, Graphical User Interface). Nous présentons dans ce chapitre :
Ouvrir ou
OK), le nom du fichier est retourné sur la variable file_name, et le chemin d'accès complet de son dossier sur la variable path. Si l'utilisateur referme cette fenêtre avec le bouton
Annuler ou
Cancel, cette fonction retourne file_name = path = 0
Ex: le code ci-dessous fait désigner par l'utilisateur un fichier, puis affiche son contenu
(pour les fonctions fopen, feof, fgetl, fprintf et fclose, voir le chapitre "Entrées-sorties formatées")
[fichier, chemin] = uigetfile('*.dat','Choisir le fichier à ouvrir :');
if ~fichier
error('Aucun fichier n''a été désigné !')
end
fid = fopen([chemin fichier], 'rt'); % entre crochets, concaténation du chemin et du nom de fichier
while ~ feof(fid)
ligne = fgetl(fid);
disp(ligne)
end
status=fclose(fid);
![]() |
![]() |
| Fenêtre uigetfile sous Windows 7 | Fenêtre uigetfile sous Ubuntu/Unity (remarquez la case à cocher "Preview" et la zone correspondante) |
Ex: [fichier, chemin] = uiputfile('resultats.dat','Sauver sous :');
Nous les présentons sous forme d'exemples, et les illustrations proviennent ici de Octave sous Windows 7.
|
Fenêtre d'information :
msg={'Message d''information', 'sur plusieurs lignes'};
msgbox(msg, 'Titre fenetre', 'none');
Le premier paramètre msg peut être une chaîne simple (qui sous
|
|
|
Fenêtre d'avertissement :
msg={'Message d''avertissement', 'sur plusieurs lignes'};
warndlg(msg, 'Titre fenetre');
Cette fonction fournit le même résultat que msgbox(msg, titre, 'warn')
|
|
|
Fenêtre d'aide :
msg={'Message d''aide', 'sur plusieurs lignes'};
helpdlg(msg, 'Titre fenetre');
Cette fonction fournit le même résultat que msgbox(msg, titre, 'help')
|
|
|
Fenêtre d'erreur :
msg={'Message d''erreur', 'sur plusieurs lignes'};
errordlg(msg, 'Titre fenetre');
Cette fonction fournit le même résultat que msgbox(msg, titre, 'error')
|
|
|
Fenêtre de question oui/non :
Cette fonction suspend l'exécution du programme et affiche une fenêtre de question. L'exécution se poursuit lorsque l'on a cliqué sur l'un des 3 boutons.
msg={'Question sur', 'plusieurs lignes'};
bouton = questdlg(msg, 'Titre fenetre','Yes')
Avec la première forme ci-dessus, affiche en-dessous du message msg les 3 boutons Cancel, No et Yes. Le 3e paramètres (facultatif, 'Yes' dans l'exemple ci-dessus) indique quel bouton est pré-sélectionné et sera activé si l'on presse enter. Retourne sur bouton la chaîne de caractère correspondant au nom du bouton pressé.
bouton = questdlg(msg, 'Titre fenetre', ...
'Annuler', 'Non', 'Oui', 'Annuler')
Avec la seconde forme ci-dessus, on spécifie le nom des boutons. Il peut y en avoir 2 ou 3 (ici 3), et on doit obligatoirement indiquer une chaîne supplémentaire spécifiant le nom du bouton activé par défaut si l'on presse enter.
|
|
|
Fenêtre de saisie de champs de texte :
Cette fonction suspend l'exécution du programme et affiche une fenêtre de saisie multi-champs. L'exécution se poursuit lorsque l'on a cliqué sur l'un des 2 boutons.
labels = {'Prenom', 'Nom', 'Pays', 'Commentaire'};
li_cols = [1, 15; 1, 15; 1, 12; 2, 20];
val_def = {'', '', 'Suisse', ''};
vec_cel = inputdlg(labels, 'Titre fenetre', li_cols, val_def)
Affiche les champs de saisie étiquetés par les chaînes du vecteur cellulaire labels.
Le paramètre li_cols (facultatif, mais nécessaire si on veut passer le paramètre val_def) permet de définir la taille des champs : Le vecteur cellulaire de chaînes val_def (paramètre facultatif) permet de pré-remplir les champs par des valeurs par défaut (ici le Pays Suisse). Lorsque l'on clique Ok, la fonction retourne les données saisies dans les différents champs sur un vecteur cellulaire de chaînes vec_cel. |
|
|
Fenêtre de sélection dans une liste :
Cette fonction suspend l'exécution du programme et affiche une fenêtre de sélection. L'exécution se poursuit lorsque l'on a cliqué sur l'un des 2 boutons inférieurs.
valeurs={'pommes','poires','cerises','kiwis','oranges'};
[sel_ind, ok] = listdlg('ListString', valeurs, ...
'Name', 'Vos fruits', ...
'PromptString', 'Fruits preferes :', ...
'SelectionMode', 'Multiple', ...
'ListSize', [100 140], ...
'InitialValue', [1, 3], ...
'OKString', 'J''ai choisi', ...
'CancelString', 'Annuler');
if ok
fprintf('Fruits choisis: ')
for ind = 1:numel(sel_ind)
fprintf([valeurs{sel_ind(ind)} ' '])
end
fprintf('\n')
end
Les paramètres d'entrée de listdlg sont définis par paire : 'mot-clé', valeur
Paramètre d'entrée obligatoire :
Paramètres d'entrée facultatifs :
Paramètres de sortie : |
|
|
Menu de choix :
choix = menu('Titre', 'element1','element2',...) ou v_cel = {'element1','element2',...} puis choix = menu('Titre', v_cel) Implémente un menu retournant dans choix le numéro d'ordre de l'élément sélectionné :
Si vous souhaitez implémenter un choix permettant de sélectionner plusieurs éléments, utilisez la fonction listdlg présentée plus haut. |
![]() |
|
Barre de progression :
handle = waitbar(fraction {,'texte'} )
Affiche une barre de progression ("thermomètre") de longueur définie par le paramètre fraction dont la valeur doit être comprise entre 0.0 (barre vide) et 1.0 (barre pleine). On utilise par exemple cette fonction pour faire patienter l'utilisateur en lui indiquant la progression d'un traitement d'une certaine durée.
barre = waitbar(0,'Patientez...');
for k=1:50
pause(0.1)
% pour les besoins de l'exemple, on
% fait ici une pause en lieu et
% place d'autres instructions...
waitbar(k/50)
end
close(barre)
|
|
|
Fenêtre de sélection de fonte/style/taille :
a) structure = uisetfont(); a) Affiche une fenêtre modale de sélection de police de caractères. Une fois que l'utilisateur a fait sa sélection, retourne sur la variable structure ce qui a été choisi, avec les champs FontName (nom de la police), FontWeight ('normal' ou 'bold'), FontAngle ('normal' ou 'italic'), FontUnits ('points'), FontSize (taille) b) Permet de modifier interactivement la fonte/style/taille de l'objet (de type: text, axes, uicontrol) spécifié par son handle h. On peut optionnellement changer le Titre de cette fenêtre de dialogue. |
|
Qt.
Les interfaces-utilisateur graphiques (GUI) sous MATLAB/Octave sont élaborées dans des fenêtres de figure/graphiques. On y place des éléments d'interface appelés contrôles graphiques (UI controls) à l'aide de fonctions ui.... À ces éléments sont associés des fonctions de callback, définies par l'utilisateur, qui sont déclenchées lorsque l'utilisateur active ces éléments (p.ex. clic sur un bouton, choix dans un menu...), ces actions étant appelées des événements. L'élaboration d'interfaces graphiques fait ainsi appel à la programmation événementielle qui s'oppose à la programmation séquentielle.
En matière de GUI, on distingue sous MATLAB/Octave les deux systèmes d'axes suivants :
De même, pour positionner un contrôle graphique, on doit spécifier les coordonnées-fenêtre (x1,y1) de son angle inférieur gauche, et sa largeur dx et hauteur dy, ou les coordonnées (x2,y2) de son angle supérieur droite. |
|
dlg = figure('name','Titre', 'menubar','none', 'numbertitle','off' {, 'property', value ...} );
Sous Octave Windows 4.4, cette fonction est un peu buguée, donc préférez-lui actuellement figure
Parmi les autres propriétés importantes dans l'initialisation de fenêtres de dialogue, mentionnons :
Une méthode alternative pour définir la position et dimension de la fenêtre est d'utiliser la commande : movegui({dlg,} position) où :
● si dlg n'est pas spécifié, la commande agit sur la fenêtre courante
● position peut prendre la forme suivante :
b) Reprend l'exécution du programme qui a été suspendu avec uiwait. Cette fonction est en principe invoquée depuis un callback.
Voir aussi la fonction waitfor(control, 'property') qui reprend l'exécution du programme lorsque la propriété proprety de l'élément control est modifiée par l'utilisateur via un callback.
a) ui_control(... , 'callback', 'code MATLAB/Octave' )
b) ui_control(... , 'callback', @fonction )
c) ui_control(... , 'callback', {@fonction, arg1, arg2 ...} )
a) Le callback est ici constitué par le code MATLAB/Octave défini sous forme de chaîne.
Ex: uicontrol('string','Fermer', 'position',[200 300 100 25], 'callback','close; disp(''bye'')');
Cette fonction crée un bouton (le 'style' par défaut étant 'pushbutton') nommé Fermer qui,
lorsqu'on clique dessus, referme la fenêtre (par un close) et affiche "bye" dans la console MATLAB/Octave.
b) Le callback est ici une fonction utilisateur, appelée sans paramètre.
c) Le callback appelle ici la fonction spécifiée en lui passant des paramètres arg1, arg2....
Noter que les accolades définissent ici bien un tableau cellulaire !
Ex: voir ci-dessous l'appel à la fonction trigo
Notez que dans certaines fonctions ui... la propriété peut être dénommée 'clickedcallback', 'oncallback' ou 'offcallback'.
function fonction(hsrc, event {, arg1, arg2 ...})
code de la fonction ...
end
|
Exemple Dans l'exemple ci-dessous illustré par la figure ci-contre, on affiche 2 champs et un popup-menu : dans le premier champ on peut introduire un angle en degrés, puis à l'aide du menu on choisit une fonction trigonométrique qui affiche, dans le second champ, le sinus ou le cosinus de l'angle. On peut quitter l'application avec le bouton Quitter ou avec le menu Fichier > Quitter. En surveillant les frappes clavier effectuées dans la fenêtre (hormis dans les champs de saisie), on définit en outre que enter a le même effet que le bouton Quitter (technique utilisée pour définir un bouton par défaut). |
|
function exemple_callback
dlg = figure('name','Exemple de callbacks', 'position',[200 500 320 100], ...
'menubar','none', 'numbertitle','off', 'KeyPressFcn',@clavier);
m1 = uimenu(dlg, 'label','&Fichier', 'accelerator','f'); % menu avec raccourci alt-f
uimenu(m1, 'label','Quitter', 'accelerator', 'q', 'callback','close'); % article avec raccourci ctrl-q
champ1 = uicontrol(dlg, 'style','edit', 'string','0', 'position',[30 60 50 25]);
champ2 = uicontrol(dlg, 'style','edit', 'position',[200 60 90 25]);
uicontrol(dlg, 'style','popupmenu', 'string',{'sin','cos'}, 'position',[100 60 50 25], ...
'callback', {@trigo, champ1, champ2});
uicontrol(dlg, 'style','pushbutton', 'string','Quitter', 'position',[120 10 80 25], 'callback','close');
end
function trigo(h,e, ch1, ch2)
angle = deg2rad(str2num(get(ch1,'string'))); % récupère angle (degrés) dans 1er champ et conversion (radians)
menu = get(h,'string'); % récupère articles du menu popup {'sin', 'cos'}
fct = menu{get(h,'value')}; % récupère l'article sélectionné
switch fct
case 'sin'
res = sin(angle);
case 'cos'
res = cos(angle);
end
set(ch2,'string', num2str(res)) % affiche le sinus ou cosinus de l'angle dans 2e champ
end
function clavier(h,e)
fprintf('La touche ''%s'' a ete pressee !\n', e.Key)
if strcmp(e.Key, 'return')
close
end
end
| Fonction et description | |
| Exemple | Illustration |
| |
Ex Menu utilisateur (illustré ci-contre avec Octave sous Ubuntu/Unity)
m1 = uimenu('label','&Fichier', 'accelerator','f'); % => alt-f
uimenu(m1, 'label','Quitter', 'accelerator','q', ...
'callback','close'); % => ctrl-q
Dans la première figure, notez bien le "F" qui apparaît en souligné. Et dans la seconde figure, la mention du raccourci "Ctrl-Q".
|
alt affiche :
alt-f affiche : |
| |
|
Ex Menu contextuel (illustré ci-contre avec Octave sous Ubuntu/Unity)
Ce menu contextuel change la colormap de la fenêtre de figure :
dlg = dialog('name','Titre', 'windowstyle','normal');
cm = uicontextmenu(dlg);
uimenu(cm, 'label','Hot', 'callback','colormap(hot)')
uimenu(cm, 'label','Winter', 'callback','colormap(winter)')
set(dlg, 'uicontextmenu',cm);
|
clic-droite affiche :
|
| Fonction et description | |
| Exemple | Illustration |
| |
| |
| |
| Exemple Dans l'exemple ci-dessous illustré par la figure ci-contre, on met en place une barre d'outils se composant de 2 boutons simples (noir et rouge) et d'un bouton à bascule (vert/cyan). Remarquez le "tooltip" (ici "Noir") qui apparaît quand on survole le bouton avec la souris, ainsi que le séparateur que l'on a mis en place entre le 2e et le 3e bouton. Vous constaterez aussi, si vous exécutez ce code, que l'on a programmé un changement d'icône du bouton à bascule selon qu'il est relâché (vert) ou enfoncé (cyan). Pour illustrer le callback de ces boutons, on affiche les événements dans la console MATLAB/Octave. |
|
function exemple_toolbar
dlg = figure('toolbar','none', 'name','Exemple de toolbar', 'numbertitle','off');
icon1 =zeros(16,16,3); # carré noir
icon2(:,:,1) =ones(16,16); icon2(:,:,2) =zeros(16,16); icon2(:,:,3) =zeros(16,16); # carré rouge
icon_off(:,:,1)=zeros(16,16); icon_off(:,:,2)=ones(16,16)/2; icon_off(:,:,3)=zeros(16,16); # carré vert
icon_on(:,:,1) =zeros(16,16); icon_on(:,:,2) =ones(16,16); icon_on(:,:,3) =ones(16,16); # carré cyan
ht = uitoolbar(dlg);
uipushtool(ht, 'cdata',icon1, 'tooltipstring','Noir', 'clickedcallback','disp(''noir'')');
uipushtool(ht, 'cdata',icon2, 'tooltipstring','Rouge', 'clickedcallback','disp(''rouge'')');
uitoggletool(ht,'cdata',icon_off, 'tooltipstring','Toggle', 'clickedcallback','disp(''clic'')', ...
'oncallback',{@toggle, icon_on}, 'offcallback',{@toggle, icon_off}, 'separator','on');
end
function toggle(h,e, icon)
disp(get(h,'state'))
set(h, 'cdata',icon)
end
| Fonction et description | |
| Exemple | Illustration |
| |
Ex 1 Boutons (illustré ci-contre avec Octave sous Ubuntu/Unity)
uicontrol('style','pushbutton', 'string','Oui', ...
'position',[10 10 50 30], 'callback','disp(''oui'')');
uicontrol('style','pushbutton', 'string','Non', ...
'position',[70 10 50 30], 'callback','disp(''non'')');
uicontrol('style','pushbutton', 'string','Quitter', ...
'position',[150 10 100 30], 'callback','close', ...
'tooltipstring','Fermer la fenetre');
|
![]() Remarquez le tooltip associé au bouton Quitter |
Ex 2 Bouton à bascule (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_togglebutton
dialog('name','Togglebutton', 'windowstyle','normal')
uicontrol('style','togglebutton', 'string','Off', ...
'position',[10 380 100 30], 'value',0, ...
'callback',@cbk_togglebutton);
end
function cbk_togglebutton(h,e)
if get(h,'value') % égal à 1 => true
set(h,'string','On'); disp('on');
else
set(h,'string','Off'); disp('off');
end
end
|
![]() Dans cet exemple, on change le libellé du bouton selon qu'il est enfoncé (On) ou relâché (Off) |
Ex 3 Texte et champ de saisie (illustré ci-contre avec Octave sous Ubuntu/Unity)
uicontrol('style','text', 'string','Nom / prenom', ...
'position',[10 380 100 30], ...
'foregroundcolor', 'b', 'backgroundcolor','w', ...
'fontangle','italic', 'horizontalalignment','left');
uicontrol('style','edit', 'string','...', ...
'position',[120 380 180 30], 'horizontalalignment','left');
|
![]() |
Ex 4 Menu déroulant (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_popupmenu
liste={'Suisse','France','Italie','Allemagne','Espagne', ...
'Belgique','Luxembourg','Portugal'};
uicontrol('style','popupmenu', 'string',liste, ...
'position',[10 380 100 30], 'callback', @cbk_popupmenu);
end
function cbk_popupmenu(h,e)
menu_itemms = get(h,'string');
disp(menu_itemms{get(h,'value')})
end
|
Menu replié... et déplié |
Ex 5 Boîte de sélection dans une liste (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_listbox
liste={'Suisse','France','Italie','Allemagne','Espagne', ...
'Belgique','Luxembourg','Portugal'};
uicontrol('style', 'listbox', 'string',liste, 'max',2, ...
'position',[10 250 100 160], 'callback', @cbk_listbox);
end
function cbk_listbox(h,e)
disp(get(h,'value'))
end
Dans cet exemple on rend possible la sélection multiple avec 'max',2
|
![]() |
Ex 6 Boîtes à cocher (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_checkbox
for k=1:5;
hcb(k)=uicontrol('style','checkbox', ...
'string',['Article ' num2str(k)], 'value',0, ...
'position',[10 400-20*k 100 20], 'callback',{@cbk_checkbox k});
end
uicontrol('style','pushbutton', 'string','Commander', ...
'position',[10 260 100 30], 'callback',{@cbk_commande hcb});
end
function cbk_checkbox(h,e, k)
if get(h,'value')
status = 'on';
else
status = 'off';
end
fprintf(' article %d %s \n', k, status)
end
function cbk_commande(h,e, hcb)
fprintf('commande articles: ')
for k=1:5
if get(hcb(k),'value') % égal à 1 => true
fprintf('%s ',num2str(k))
end
end
fprintf('\n')
end
|
![]() Dans cet exemple, chaque clic active le callback "cbk_checkbox". De plus le bouton Commander active le callback "cbk_commande" qui relève l'état de toutes les boîtes à cocher. |
Ex 7 Curseur (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_slider
uicontrol('style','text', 'string','Température', ...
'position',[10 370 100 30]);
uicontrol('style','slider', 'position', [130 375 250 15], ...
'min',-10, 'max',30, 'value',0, ...
'callback', @cbk_slider);
end
function cbk_slider(h,e)
disp(get(h,'value'))
end
|
![]() |
| |
Ex 8 Groupe de boutons radio (illustré ci-contre avec Octave sous Ubuntu/Unity)
function test_uibuttongroup
hbg = uibuttongroup('title','Sexe', ...
'position',[.05 .65 .25 .3]); % unités normalisées !!!
uicontrol(hbg, 'style','radiobutton', 'string','Femme', ...
'value',0, 'position',[10 80 100 20], 'callback',{@cbk_radio 'femme'});
uicontrol(hbg, 'style','radiobutton', 'string','Homme', ...
'value',0, 'position',[10 50 100 20], 'callback',{@cbk_radio 'homme'});
uicontrol(hbg, 'style','radiobutton', 'string','N/A', ...
'value',1, 'position',[10 20 100 20], 'callback',{@cbk_radio 'n/a'});
end
function cbk_radio(h,e, sexe)
if get(h,'value')
disp(sexe)
end
end
|
![]() Notez que le choix initial du bouton pressé est défini par celui qui a la propriété 'value',1, donc ici "N/A". Notez aussi que les 3 boutons étant liés (exclusifs), le clic sur l'un génère exactement 2 appels au callback : pour le passage à On de celui que l'on clique, et pour le passage automatique à Off de celui qui était à On. |
| |
Ex 9 Panels imbriqués (illustré ci-contre avec Octave sous Ubuntu/Unity)
dialog('name','Exemple de uipanel', 'windowstyle','normal')
hp = uipanel('title','Panel principal', 'position',[.1 .1 .8 .66], ...
'fontsize',16, 'backgroundcolor','white');
hsp1= uipanel(hp,'title','Sous-panel 1', 'position',[.1 .1 .4 .4], ...
'fontsize',12, 'backgroundcolor','y'); % sous-panel du panel hp
hsp2= uipanel(hp,'title','Sous-panel 2', 'position',[.6 .1 .3 .4], ...
'fontsize',12, 'backgroundcolor','c'); % sous-panel du panel hp
uicontrol(hsp1,'string','Fermer', 'position',[15 15 80 30], ...
'callback','close'); % bouton dans le sous-panel 1
uicontrol('style','text', 'string','Exemple uipanel', ...
'units','normalized', 'position', [.1 .85 .8 .1], ...
'foregroundcolor', 'w', 'backgroundcolor',[.4 .4 .4], ...
'horizontalalignment','center', 'fontangle','italic', ...
'fontsize',20); % texte en-dehors des panels
|
|
Remarque : sous Octave, la fonction uitable fait son apparition avec la version 5.
| Fonction et description | |
| Exemple | Illustration |
| |
Ex
personnes={
'Jules','Dupond',24
'Albertine','Durand',30
'Robert','Muller',28
} ;
entete_col={'Prenom', 'Nom', 'Age'} ;
coul_alternee=[1 1 1 ; 1 1 .8] ;
dlg = figure('name','Utilisateurs', 'menubar','none', ...
'numbertitle','off', 'position',[10 10 350 200]) ;
movegui(dlg,'west')
htab=uitable(dlg, 'Data',personnes, ...
'ColumnName',entete_col, ...
'ColumnWidth',{120 120 30}, ...
'ForegroundColor','b', ...
'BackgroundColor',coul_alternee, ...
'Position',[20 20 300 150] ...
) ;
|
|
| Fonction et description | |
| Exemple | Illustration |
| |
Ex Les différents types d'annotations (illustré ci-contre avec Octave sous Ubuntu/Unity)
dialog('name', 'Exemple d''annotations', ...
'WindowStyle', 'normal') % dialogue non "modal"
% ou commande "figure"
annotation('line', [.5 .9], [.1 .6], 'color','b', ...
'linewidth',4, 'linestyle',':')
annotation('arrow', [.2 .4], [.9 .6], 'color',[0 .5 0], ...
'linewidth',3, 'linestyle','--')
annotation('doublearrow', [.35 .6], [.45 .45], ...
'color','g', 'linewidth',3, 'linestyle','-')
annotation('textarrow', [.7 .6], [.8 .6], ...
'string','annotation')
annotation('textbox', [.5 .5 0 0], 'string', 'Hello !', ...
'fontsize',30, 'horizontalalignment','center', ...
'color','r', 'edgecolor','none', 'backgroundcolor','none')
annotation('rectangle', [.15 .1 .25 .2],'facecolor',[1 1 0], ...
'edgecolor',[.5 .5 0],'linewidth',6, 'linestyle','-')
annotation('ellipse', [.8 .1 .1 .3], ...
'facecolor',[.8 .8 1],'edgecolor','none')
|
|
![]() |
![]() |
![]() |
| Figure 1 | Figure 2 | Figure 3 |
![]() |
![]() |
| Figure 4 | Figure 5 |
function appli_gui % Programme principal
disp('Application graphique "modale" (à piloter depuis fenetre graphique)')
global dlg
dlg = figure('name','Application GUI (voir menus)', 'menubar','none', 'numbertitle','off');
% ou: dlg = dialog('name', 'Application GUI (voir menus)', 'windowstyle','normal');
screen_size = get(0,'screensize') ; % taille de l'écran
screen_center = screen_size(3:4)/2 ; % coordonnées x/y du centre de l'écran
dialog_size = [600 400] ; % taille de la fenetre d'application
dialog_pos = screen_center - dialog_size/2 ; % pour centrer fenetre sur l'écran
set(dlg, 'position',[dialog_pos dialog_size], 'color',[.8 .8 .8])
dialog_init
uiwait(dlg); % utile lorsque 'windowstyle' est à 'normal' pour que l'appli tourne de façon modale
end
% ***** Initialisation fenetre GUI (menus, boutons) ********************************************************************
function dialog_init
global dlg
clf(dlg) % efface la fenetre (y compris menus ; sinon utiliser "cla(handle)")
m1 = uimenu(dlg, 'label','&Fichier', 'accelerator','f'); % => alt-f
uimenu(m1, 'label','Quitter', 'accelerator','q', 'callback', @quitter); % => ctrl-q
m2 = uimenu(dlg, 'label','&Calculette', 'accelerator','c'); % => alt-c
uimenu(m2, 'label','Arithmetique', 'accelerator','a', 'callback', @calc_arith); % => ctrl-a
uimenu(m2, 'label','Trigonometrique', 'accelerator','t', 'callback', @calc_trigo); % => ctrl-t
m3 = uimenu(dlg, 'label','&Graphiques', 'accelerator','g'); % => alt-g
uimenu(m3, 'label','Sinus et Cosinus', 'accelerator','n', 'callback', @graph_sincos); % => ctrl-n
uimenu(m3, 'label','Surface 3D', 'accelerator','s', 'callback', @graph_3d); % => ctrl-s
m4 = uimenu(dlg, 'label','&Aide', 'accelerator','h'); % => alt-a
uimenu(m4, 'label','Infos', 'accelerator','i', 'callback', @infos); % => ctrl-i
uicontrol(dlg, 'style','pushbutton', 'string','Infos', 'units','normalized', 'position',[.05 .05 .15 .1], 'callback', @infos);
uicontrol(dlg, 'style','pushbutton', 'string','Quitter', 'units','normalized', 'position',[.8 .05 .15 .1], 'callback', @quitter);
global erreur
erreur = uicontrol('style','text', 'visible','off', 'units','normalized', 'position',[.1 .25 .8 .06], ...
'horizontalalignment','center', 'foregroundcolor','r', 'backgroundcolor',[1 .8 .8]);
% ou: erreur = annotation(dlg, 'textbox', [.1 .25 .8 .06], 'visible','off', 'horizontalalignment','center', ...
% 'color','r', 'backgroundcolor',[1 .8 .8], 'edgecolor','none', 'fitboxtotext','off');
end
% ***** Calculette Arithmétique ****************************************************************************************
function calc_arith(h,e)
dialog_init
ch1 = uicontrol('style','edit', 'string','0', 'units','normalized', 'position',[.2 .6 .2 .07]);
ch2 = uicontrol('style','edit', 'string','0', 'units','normalized', 'position',[.6 .6 .2 .07]);
uicontrol('style','text', 'string', '=>', 'units','normalized', 'position',[.25 .4 .1 .07], 'backgroundcolor',[.8 .8 .8]);
ch3 = uicontrol('style','edit', 'units','normalized', 'position',[.35 .4 .3 .07]);
uicontrol('style','pushbutton', 'string','+', 'units','normalized', 'position',[.46 .65 .07 .07], ...
'callback', {@c_arith, '+', ch1, ch2, ch3});
uicontrol('style','pushbutton', 'string','-', 'units','normalized', 'position',[.46 .55 .07 .07], ...
'callback', {@c_arith, '-', ch1, ch2, ch3});
end
function c_arith(h,e, oper, ch1, ch2, ch3)
nb1=str2num(get(ch1,'string'));
nb2=str2num(get(ch2,'string'));
global erreur % handle vers la zone d'affichage d'erreur
if isempty(nb1) && isempty(nb2)
set(erreur, 'string', 'Erreur: les deux champs ne contiennent pas de nombres', 'visible','on')
set(ch1, 'backgroundcolor','y'); set(ch2, 'backgroundcolor','y');
elseif isempty(nb1)
set(erreur, 'string', 'Erreur: le 1er champ ne contient pas un nombre', 'visible','on')
set(ch1, 'backgroundcolor','y'); set(ch2, 'backgroundcolor','w');
elseif isempty(nb2)
set(erreur, 'string', 'Erreur: le 2e champ ne contient pas un nombre', 'visible','on')
set(ch1, 'backgroundcolor','w'); set(ch2, 'backgroundcolor','y')
else
set(erreur, 'visible','off')
set(ch1, 'backgroundcolor','w'); set(ch2, 'backgroundcolor','w')
switch oper
case '+'
set(ch3, 'string',num2str(nb1+nb2))
case '-'
set(ch3, 'string',num2str(nb1-nb2))
end
end
end
% ***** Calculette Trigonométrique *************************************************************************************
function calc_trigo(h,e)
dialog_init
champ1 = uicontrol('style','edit', 'string','0', 'units','normalized', 'position',[.25 .6 .15 .07]);
uicontrol('style','text', 'string','degres =>', 'units','normalized', 'position',[.4 .6 .15 .07], 'backgroundcolor',[.8 .8 .8]);
champ2 = uicontrol('style','edit', 'string',' ', 'units','normalized', 'position',[.6 .6 .30 .07]);
uicontrol('style','popupmenu', 'string',{'sin','cos','tan'}, 'horizontalalignment','center', ...
'units','normalized', 'position',[.1 .6 .12 .07], 'callback', {@c_trigo, champ1, champ2});
end
function c_trigo(h,e, ch1, ch2)
angle = deg2rad(str2num(get(ch1,'string')));
menu = get(h,'string');
choix = get(h,'value');
switch (menu{choix})
case 'sin'
res=sin(angle);
case 'cos'
res=cos(angle);
case 'tan'
res=tan(angle);
end
set(ch2, 'string',num2str(res))
end
% ***** Graphique Sinus et Cosinus *************************************************************************************
function graph_sincos(h,e)
dialog_init
global dlg
uicontrol(dlg, 'style','pushbutton', 'string','sinus', 'units','normalized', 'position',[.8 .52 .15 .1], ...
'callback', {@g_sincos, 'sin'});
uicontrol(dlg, 'style','pushbutton', 'string','cosinus', 'units','normalized', 'position',[.8 .40 .15 .1], ...
'callback', {@g_sincos, 'cos'});
end
function g_sincos(h,e, fct)
fplot(fct, [0 4*pi])
title(fct,'fontsize',16)
grid('on')
end
% ***** Graphique Surface 3D *******************************************************************************************
function graph_3d(h,e)
dialog_init
global dlg
eclairage = 1 ; elevation = 30 ; orientation = 30 ;
g3d(eclairage, orientation, elevation)
uicontrol('style','text', 'string','Orientation', 'units','normalized', 'position',[.05 .87 .15 .1], 'backgroundcolor',[.8 .8 .8]);
uicontrol(dlg, 'style','slider', 'min',0, 'max',90, 'value',orientation, 'units','normalized', 'position',[.20 .9 .25 .04], ...
'callback', {@g3d_orient, elevation});
uicontrol('style','text', 'string','Eclairage', 'units','normalized', 'position',[.5 .87 .15 .1], 'backgroundcolor',[.8 .8 .8]);
uicontrol(dlg, 'style','slider', 'min',0, 'max',1, 'value',eclairage, 'units','normalized', 'position',[.65 .9 .25 .04], ...
'callback', @g3d_eclair);
end
function g3d(eclair, orient, elev)
handle = surf(peaks(100));
set(get(handle, 'parent'), 'position',[.2 .15 .6 .7]) % diminution taille zone graphique
set(gca,'xticklabel',[],'yticklabel',[],'zticklabel',[]) % ou: axis('nolabel') sous Octave
shading('interp')
view(orient, elev)
global heclair
heclair = light('color',[eclair eclair eclair]); % source de lumière blanche
end
function g3d_orient(h,e, elevation)
orientation = get(h, 'value') ;
view(orientation, elevation)
end
function g3d_eclair(h,e)
global heclair
eclair = get(h, 'value') ;
set(heclair, 'color',[eclair eclair eclair])
end
% ***** Aide et Sortie *************************************************************************************************
function infos(h,e)
dialog_init
texte = sprintf([ ...
'Cette application illustre la programmation d''une \n' ...
'interface-utilisateur graphique (GUI) sous MATLAB \n' ...
'ou Octave GUI. \n\n' ...
'Elle s''execute de façon "modale" en interagissant avec \n' ...
'les menus (au haut de le fenetre) et boutons. \n' ...
]);
uicontrol('style','text', 'string',texte, 'units','normalized', 'position',[.05 .4 .9 .4], ...
'horizontalalignment','left', 'fontsize',13);
end
function quitter(h,e)
uicontrol('style','text', 'string','Au revoir !', 'units','normalized', 'position',[.3 .05 .4 .1], ...
'horizontalalignment','center', 'fontsize',25, 'backgroundcolor',[.8 .8 .8]);
pause(1)
close(gcf) % ou: delete(gcf)
end
% **********************************************************************************************************************