MATLAB – przykłady użycia Handle Graphics i graficznego interfejsu użytkownika (GUI)

 

Uwaga. Wszystkie M-pliki zamieszczone na tej stronie są do pobrania z tabeli znajdującej się na głównej stronie przykładów

 

Prosta animacja obiektów graficznych

Interaktywne wykresy 3D

Interaktywne wykresy 2D

Interaktywne sterowanie rozkładem kolorów

Interaktywne sterowanie obiektami - użycie własności ButtonDownFcn

 

Przykład 1. Program robaczek.m. Budowanie „od zera” obiektów graficznych i prosta animacja.

%ROBACZEK.M

%ilustracja prostej animacji przy pomocy HANDLE GRAPHICS

%w połączeniu z wysokopoziomowymi poleceniami graficznymi

a = 2;

ile = 200;

x = linspace(-a,a,ile);

y = x.^2-a/2;

skala = [-a:1:a];

okno = figure;

set(gcf,'NumberTitle','Off','MenuBar','None','Name','Robaczek zjada parabolę');

uklad = newplot;

parabola = plot(x,y,'.');

%sprawdź, co się dzieje, gdy w linijce niżej ustawisz własność 'Erase' na 'Normal' lub 'xor'

wykres = line('color','b','marker','o','Erase','Background', ...

   'MarkerFace','red','MarkerSize',12,'xdata',x(1:3),'ydata',y(1:3));

set(uklad,'XLim',[-a,a],'XTick',[]);

set(uklad,'YLim',[-a,a],'YTick',[]);

shg;

for k = 5:ile;

   set(wykres,'XData',x(k-4:k),'YData',y(k-4:k));

   pause(0.02);

   drawnow;

end;

cla;

kontrolatempa = [0.1 : 0.02: 1];

for k = kontrolatempa

 text(0,0,'Popatrz jak ten napis znika...',...

    'FontSize',16,'FontWeight','Bold','HorizontalAlignment','Center','Color',[k k k]);

 pause(0.05);

end;

cla;

set(uklad,'Color',[0 0 0]);

set(gcf,'KeyPressFcn',...

   'if double(get(okno,''CurrentCharacter''))==27,close(gcf),end');

text(0,0,'ESC ZAMYKA OKNO','Color','r','FontSize',20,...

   'FontWeight','Bold','HorizontalAlignment','Center');

 

 

 

Okno programu robaczek.m w czasie trwania animacji

 

 

 

 

Przykład 2. Program wykresy3d. Zastosowanie elementów graficznego interfejsu użytkownika. Program rysuje powierzchnie o równaniach parametrycznych podanych przez użytkownika.

 

%WYKRESY3D.M

%program ilustrujący mechanizmy Graphical User Interface Matlaba

%Ilustracja obiektów FIGURE, AXES, UICONTROL

%program pozwala na wprowadzenie równań parametrycznych powierzchni w R^3

%-------------------------------------------------------

xstr = 's*cos(t)'; %początkowe równania x(s,t), y(s,t), z(s,t);

ystr = 's*sin(t)';

zstr = 's';

scrsz = get(0,'ScreenSize');%odczytujemy rozmiary ekranu komputera

figure('Position',[0.2 0.2 0.6 0.6].*scrsz([3 4 3 4]));%kreujemy okno graficzne i ustalamy rozmiar

ezsurf(xstr,ystr,zstr);%rysujemy powierzchnie daną równaniami

set(gcf,'NumberTitle','Off');%ustalamy kilka własności okna graficznego - obiekt FIGURE

set(gcf,'Name','Wykresy 3D');

%set(gcf,'MenuBar','None');

set(gca,'Position',[0.05 0.2 0.85 0.7 ]);%ustalamy polozenie obiektu AXES - układu współrzędnych

pozycjaetykiety = [10 60 50 20];%pozycja pierwszej etykiety pola edycyjnego

przesuniecie = [50 0 50 0];%przesuniecie pola edycyjnego wzgl. etykiety

skok = [0 -25 0 0];%położenie nastepnej etykiety

%definiujemy po kolei etykiety pól edycyjnych i same pola

%----- pole do edycji x(s,t)

tip = 'Wpisz wyrazenie zmiennych s i t';

uicontrol('Style','text','Position',pozycjaetykiety,'String',...

   'y(s,t) = ','ForegroundColor','b','FontWeight','Bold');

polex = uicontrol('Style','Edit','Position',pozycjaetykiety+przesuniecie,'String',xstr,...

   'BackgroundColor','w','HorizontalAlignment','Left','TooltipString',...

   tip,'FontWeight','Bold');

%----- pole do edycji y(s,t)

pozycjaetykiety = pozycjaetykiety + skok;

uicontrol('Style','text','Position',pozycjaetykiety,'String',...

   'y(s,t) = ','ForegroundColor','b','FontWeight','Bold');

poley = uicontrol('Style','Edit','Position',pozycjaetykiety+przesuniecie,'String',ystr,...

   'BackgroundColor','w','HorizontalAlignment','Left','TooltipString',...

   tip,'FontWeight','Bold');

pozycjaetykiety = pozycjaetykiety + skok;

%----- pole do edycji z(s,t)

uicontrol('Style','text','Position',pozycjaetykiety,'String',...

   'z(s,t) = ','ForegroundColor','b','FontWeight','Bold');

polez = uicontrol('Style','Edit','Position',pozycjaetykiety+przesuniecie,'String',zstr,...

   'BackgroundColor','w','HorizontalAlignment','Left','TooltipString',...

   tip,'FontWeight','Bold');

%definiujemy przyciski

pozycjapola = [10,30,100,20];

pozycjaguzika1 = pozycjaetykiety + przesuniecie + [200 0 20 20];

pozycjaguzika2 = pozycjaguzika1 + [200 0 20 0];;

guzik1 = uicontrol('Style','PushButton','String','Rysuj teraz',...

   'Position',pozycjaguzika1,'Callback',...

   'ezsurf(get(polex,''String''),get(poley,''String''),get(polez,''String''))');

guzik2 = uicontrol('Style','PushButton','String','Koniec',...

   'Position',pozycjaguzika2,'Callback',...

   'close(gcf)');

shg;

 

Okno programu wykresy3d.m

 

 

Przykład 3. Program ambitnewykresy.m. Ilustracja obsługi zdarzeń przez zewnętrzną M-funkcję oraz ilustracja użycia gotowych okien dialogowych Matlaba.

Główny program wyświetla okno graficzne, w którym rysowane są wykresy funkcji jednej zmiennej. Za pośrednictwem pomocniczego okna dialogowego użytkownik może zdefiniować wyrażenie określające funkcję, przedział, w którym ma być narysowana oraz  liczbę punktów podziału dla funkcji plot.

 

Główny program

%AMBITNEWYKRESY.M

%Prosty przyklad graphical user interface

%program rysuje wykres zadanej funkcji w zadanym przedziale

%dokladnie przestudiuj pliki parametrydialog.m i rysujwgparametrow.m

%pamietaj, ze po zakonczeniu pracy tego programu

%okno graficzne jest caly czas aktywne, a przyciski "wrazliwe" na nacisniecie

h = figure; %otwieramy nowe okno graficzne

%ilustracja własności "Modal" - bez zamknięcia okna nie da się używać innych elementów Matlaba

set(h,'WindowStyle','Modal');

set(h,'NumberTitle','Off');

set(h,'Name','Rysowanie krzywych postaci y = f(x)');

uklad = newplot;%jest to zalecany sposob kreowania układu wspolrzednych;

set(uklad,'xlim',[0,2*pi],'ylim',[-1, 1]);

axis([0 1 0 1]);

%definiujemy przyciski akcji

ppg = [20 10]; %polozenie lewego dolnego rogu pierwszego guzika

dlugguzika = 60;

wysguzika = 20;

%definicja przycisku uruchamiającego okno dialogowe parametrów

guzikparametrow = uicontrol('Style','PushButton','String','Parametry','Position',...

   [ppg, dlugguzika, wysguzika]);

%definicja przycisku ZAMKNIJ

guzikzamknij = uicontrol('Style','PushButton','String','Zamknij','Position',...

   [ppg(1)+dlugguzika+5, ppg(2), dlugguzika, wysguzika]);

 

%inicjujemy domyślne parametry i zapisujemy je we własności 'UserData' okna graficznego

biezaceparametry  = {'exp(-x/20).*sin(x)';'0';'20*pi';'200'};

%zapamietujemy je we własności 'UserData' okna graficznego

set(gcf,'UserData',biezaceparametry);

%robimy pierwszy rysunek - patrz M-funkcja wywolywana w nastepnej linijce

obsluga rysuj;

 

%podlaczamy obsługę zdarzeń do przycisków;

set(guzikparametrow,'Callback','obsluga parametrydialog');

set(guzikzamknij,'Callback','obsluga zamknij');

set(guzikzamknij,'Callback','obsluga zamknij');

 

Okno programu ambitnewykresy.m

 

Poniżej zamieszczona jest pomocnicza M-funkcja realizująca obsługę zdarzeń polegających na naciśnięciu jednego z przycisków w oknie programu ambitnewykresy.m.

 

----------------------- (Początek M-pliku zawierającego funkcję)

 

function obsluga(akcja);

%obsluga zdarzeń w oknie głównym programu AMBITNEWYKRESY

switch akcja

case 'rysuj'

   rysujwgparametrow;

case 'parametrydialog'

   ustawparametry;

case 'zamknij'

   zamknijokno;

end;

 

 

function ustawparametry;

Zachety = {'Funkcja f(x) = ...','Lewy koniec [a, b]',...

            'Prawy koniec [a, b]','Liczba punktow podzialu'};

Tytul    = 'Dane do wykresu';

liczbalinijek = 1;

parametry = get(gcbf,'UserData'); %używamy gcbf, ale można też gcf;

%ilustracja wbudowanego w Matlaba okna dialogowego inputdlg;

noweparametry = inputdlg(Zachety,Tytul,liczbalinijek,parametry);

%jesli user nacisnal Cancel, to noweparametry = {}

if isempty(noweparametry)

   return

else

   set(gcbf,'UserData',noweparametry);

   rysujwgparametrow;

end;

 

function zamknijokno;

%m.in. ilustracja wbudowanego w Matlaba okna dialogowego questdlg;

tytul = 'Pytanie:';

wynik = questdlg('Czy zamknac okno graficzne?',tytul,'Tak','Nie','Nie');

if strcmp(wynik,'Tak')

   close(gcf);

end;

 

%funkcja niżej nie jest bezpośrednio wywoływana przez zdarzenia

%lecz przez główny program i przez funkcję USTAWPARAMETRY

function rysujwgparametrow;

nazwypol = {'funkcja','lewykoniec','prawykoniec','ilepunktow'};

parametry = get(gcf,'UserData');

s = cell2struct(parametry,nazwypol,1);

%napisz help cell2struct, zeby zrozumieć,

%dlaczego w ostatnim wywolaniu dajemy parametr DIM = 1;

x = linspace(eval(s.lewykoniec),eval(s.prawykoniec),eval(s.ilepunktow));

y = eval(s.funkcja);

plot(x,y,'LineWidth',2);

axis([min(x) max(x) min(y) max(y)]);

Title(['\bf Wykres funkcji y = ', s.funkcja],'Color','red');

 

-------------------- (Koniec M-pliku)

 

 

 

Okno dialogowe wyświetlane przez Matlaba po naciśnięciu przycisku “Parametry”

 

 

 

Przykład 4 Program suwakdemo.m. Ilustracja użycia suwaka do sterowania kolorami powierzchni.

 

%SUWAKDEMO.M

%ilustracja sterowania skalą kolorów za pomocą suwaka

maksimum = 20;

zakresxy = [0 3 0 2*pi];

wyrx = '2*r*cos(t)'; wyry = 'r*sin(t)';wyrstozek = '3*r';

ezsurf(wyrx,wyry,wyrstozek,zakresxy,30);

colormap hsv;

caxis([0 maksimum]);

slupek = colorbar;

view(-37.5,10);

suwak = uicontrol('Style','Slider','Min',1,'Max',maksimum,...

   'Value',maksimum,'Position',[10 10 20 200],'SliderStep',[1/(2*(maksimum-1)) 1/(maksimum-1)]);

pole = uicontrol('Style','Edit','Position',[40,10,80,20],'BackgroundColor','white',...

   'Enable','Off','Value',maksimum,'String',num2str(maksimum),'HorizontalAlignment','Left');

akcjasuwaka = ...

   ['wartosc = get(suwak,''Value'');set(pole,''Value'',wartosc);',...

      'set(pole,''String'',num2str(wartosc));',...

      'caxis([0 wartosc]);colorbar'];

set(suwak,'Callback',akcjasuwaka);

 

 

 

Okno programu suwakdemo.m

 

 

 

Przykład 5. Program buttondown.m. Ilustracja użycia własności ButtonDownFcn do sterowania obiektami.

 

Następujący program kreuje okno graficzne, rysuje wykresy 3 funkcji, a następnie definiuje obsługę własności ButtonDownFcn dla wykreowanych obiektów AXES oraz LINE. Kliknięcie w którykolwiek z wykresów zmienia jego grubość. Kliknięcie w obszar układu współrzędnych poza wykresami rysuje czarny punkt w miejscu kliknięcia. Kliknięcie w istniejący punkt usuwa go. Obsługą opisanych operacji zajmuje się funkcja OBSLUGABUTTONDEMO.M. Funkcja ta musi znajdować się na ścieżce dostępu Matlaba (zaleca się umieszczenie jej w tym samym katalogu, co główny program).

 

Uwaga. Zauważ, że właściwość ButtonDownFcn umożliwia interakcję z obiektami graficznymi bez użycia funkcji Matlaba ginput.

 

%BUTTONDOWNDEMO.M

%program ilustrujący użycie własności ButtonDownFcn obiektów LINE oraz AXES

%aby program działał prawidłowo, należy na ścieżce Matlaba umieścić

%funkcję obsługi zdarzeń OBSLUGABUTTONDOWN.M

%-----------------

%PROGRAM RYSUJE WYKRESY 3 FUNKCJI

%KLIKNIECIE W WYKRES ZMIENIA JEGO GRUBOŚĆ

%KLIKNIĘCIE POZA WYKRESEM "RYSUJE" CZARNY PUNKT

%KLIKNIĘCIE W NARYSOWANY WCZEŚNIEJ PUNKT USUWA GO

t = linspace(0,4*pi,500);

a = 5; b = 10;

y = [exp(-t/a);-exp(-t/a);exp(-t/a).*sin(b*t)];

h = plot(t,y,'LineWidth',2);

uklad = gca;

Title('Kliknij w którąś krzywą lub obszar układu współrzędnych','FontName','Arial CE','FontWeight','Bold','FontSize',12);

set(h,'ButtonDownFcn','set(gcbo,''LineWidth'',6 - get(gcbo,''LineWidth''))');

set(uklad,'ButtonDownFcn','obslugabuttondown uklad');

 

Funkcja obsługi zdarzeń programu BUTTONDOWNDEMO.M:

 

%OBSLUGABUTTONDOWN.M

%FUNKCJA OBSŁUGI ZDARZEŃ PROGRAMU BUTTONDOWNDEMO.M

function obslugabuttondown(akcja);

switch akcja

case 'krzywe'

   set(gcbo,'LineWidth',6 - get(gcbo,'LineWidth'));

case 'uklad'

   punkt = get(gca,'CurrentPoint');

   x = punkt(1,1); y = punkt(1,2);

   line('XData',punkt(1,1),'YData',punkt(1,2),...,

      'Marker','o','MarkerFace','k','MarkerSize',6,...,

      'EraseMode','Background','ButtonDownFcn','obslugabuttondown punkcik');

case 'punkcik'

   delete(gcbo);

end

 

Rysunek niżej przedstawia okno programu po kliknięciu przez użytkownika jednej z krzywych i kilku punktów układu współrzędnych.

 

 

Okno programu buttondowndemo.m

 

 

 

Przykład 6. Program movedemo.m. Ilustracja użycia własności ButtonDownFcn do przesuwania obiektu graficznego.

Następujący program kreuje okno graficzne, rysuje czerwoną kropkę na płaszczyźnie, a następnie definiuje obsługę własności ButtonDownFcn dla obiektu LINE, którym jest narysowana kropka. Kropkę można przesuwać myszą na zasadzie „drag and drop”. Kliknięcie w obszar układu współrzędnych poza kropką powoduje jej „przybiegnięcie” do punktu kliknięcia (spróbuj się tym pobawić: kliknij krótko w biały obszar poza kropką i ucieknij myszą z tego miejsca; po paru chwilach odniesiesz wrażenie, że bawisz się z czerwoną kropką w „kotka i myszkę”).

 

Obsługą zdarzeń programu zajmuje się funkcja OBSLUGAMOVE.M. Funkcja ta musi znajdować się na ścieżce dostępu Matlaba (zaleca się umieszczenie jej w tym samym katalogu, co główny program).

 

 

%MOVEDEMO.M

%ILUSTRACJA WŁASNOŚCI ButtonDownFcn obiektu LINE

h = figure;

uklad = newplot;

punkt = plot(0,0,'o-','MarkerFace','r','MarkerEdge','r','MarkerSize',6,'EraseMode','Background');

set(uklad,'ButtonDownFcn','obslugamove przyjdzdomnie');

axis([-3 3 -3 3]);

axis equal;

set(punkt,'ButtonDownFcn','obslugamove start','Tag','mojpunkt');

Title('Przesuwaj czerwony punkt myszą. Klikaj też w biały obszar.',...,

   'FontWeight','Bold','FontName','Arial CE','Color','b');

 

 

Funkcja obsługi zdarzeń programu MOVEDEMO.M jest niżej. Wytłumacz na podstawie kodu, dlaczego kulka „przybiega” do punktów kliknięcia z różnymi prędkościami. W szczególności powiedz, w której linijce można wyczytać prędkość ruchu kulki.

 

%FUNKCJA OBSŁUGI ZDARZEŃ PROGRAMU MOVEDEMO.M

function obslugamove(akcja)

switch akcja

case 'start'

   set(gcbf,'WindowButtonMotionFcn','obslugamove ruch');

   set(gcbf,'WindowButtonUpFcn','obslugamove stop');

case 'ruch'

   pkt = get(gca,'CurrentPoint');

   set(gco,'XData',pkt(1,1));

   set(gco,'YData',pkt(1,2));

   drawnow;

case 'stop'

   set(gcbf,'WindowButtonMotionFcn','');

   set(gcbf,'WindowButtonUpFcn','');

case 'przyjdzdomnie'

   biezacypkt = get(gca,'CurrentPoint');

   nowex = biezacypkt(1,1); nowey = biezacypkt(1,2);

   mojobiekt = findobj('Tag','mojpunkt');

   starex = get(mojobiekt,'XData');

   starey = get(mojobiekt,'YData');

   p0 = [starex starey]; p1 = [nowex nowey];

   for t = 0 : 0.001: 1

      biezacy = p0+t*(p1-p0);

      set(mojobiekt,'XData',biezacy(1),'YData',biezacy(2));

      drawnow;

   end;

  

end;%switch