F5: Grafiska användargränssnitt (kap. 9 10) Vad är ett (grafiskt) användargränssnitt? Ett exempel: Enkel räknare p 1 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Grafiska objekt och egenskapslistor Grafikfunktioner returnerar en objektreferens. >> obj_r = quiver([0 1],[0 0],[1 0],[1 1],'o') obj_r = 111.001 Objektet som refereras är en struct med MÅNGA fält p 2 (38) Staffan Romberger, CSC, KTH, 2010-11-21
>> get(obj_r) Color = [0 0 1] EraseMode = normal LineStyle = none LineWidth = [0.5] Marker = o MarkerSize = [6] MarkerEdgeColor = auto MarkerFaceColor = none XData = [0 1] YData = [0 0] ZData = [] BeingDeleted = off ButtonDownFcn = Children = [] Clipping = on CreateFcn = DeleteFcn = BusyAction = queue HandleVisibility = on HitTest = on Interruptible = on Parent = [107.001] Selected = off SelectionHighlight = on Tag = Type = line UIContextMenu = [] UserData = [] Visible = on p 3 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Man kan med get(obj_r, 'egenskapsnamn') resp. set(obj_r, 'egenskapsnamn', värde) avläsa resp. ändra egenskaperna. set(obj_r, Visible, off ) grafobj_1, grafobj_2 Återanropsfunktioner (callback) Objekten kan vara beredda på vissa händelser (tryck på knapp, retur i textobjekt o.d.) och hålla reda på vad som ska göras. Det definieras i en tillhörande callback återanropsfunktion. Normalt anropas en funktion med namnet objektnamn_callback i gränssnittets m-fil p 4 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Gränssnittsbyggaren guide Gränssnitt kan byggas med enbart kommandon men det är smidigare att använda gränssnittsbyggaren guide. Arbetsgång (top-down) Skissa gränssnittet. Skapa objekten med guide. Sätt egenskaperna med guide. 56 Spara..m-fil och.fig-fil sparas. Skriv återanropsfunktionerna och andra programdelar, först bara med dummy - funktionalitet för kontroll att logiken stämmer. Testa. + - Quit Exempel: Räknaren En knapp räknar upp, en räknar ner; Värdet visas i en textruta. En knapp med Quit: p 5 (38) Staffan Romberger, CSC, KTH, 2010-11-21
p 6 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Med egenskapseditorn ( inspector ) justerar man objektens egenskaper. T ex Position(x,y,width,height) Här betyder (x,y) objektets läge i förhållande till föräldra-objekt och (width,height) objektets storlek, allt angivet i måttenheten enligt egenskapen Units. Gränssnittskomponenter Skärmen är objektet root. Fönster som är objekt av typ figure och ligger på skärmen. Koordinatsystem (ritområden) som är av typ axes och ligger i ett fönster. Fönstermenyer som är av typ uimenu och hör till ett fönster. Markörmenyer som är av typ uicontextmenu och hör till ett fönster. Gränssnittsobjekt av typ uicontrol p 7 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Knappar är av typ pushbutton. Textrutor är av typ edit. ---Lab3: hur göra flera rader och rullningslist? egenskaper max och min! Skyltar är av typ text. Radioknappar är av typ radiobutton. Kryssrutor är av typ checkbox. Vallistor är av typ listbox. Skjutreglage är av typ slider. Rutor är av typ frame Många slags objekt finns i koordinatsystem. p 8 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Vi använde : pushbutton1..3 och en Skylt (som kallades text2). Texten på skylten läses resp skrivs med get(h.text2, String ) set(h.text2, String,num2str(COUNTER)) där h är en referens till den struktur handles som håller alla objekten i GUI. Den är in-parameter till alla xxx_callback som skapas av GUIDE och ger åtkomst till alla objektens data i alla callbacks.! Skylten är bara för utmatning och har ingen callback, så syns inte i GUIprogrammet, bara i GUI-objektet! p 9 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Programskelett Guide konstruerar ett programskelett där man bl.a. ska modifiera återropsfunktionerna. Modifikationer med rött nedan Skelettet i plusminus.m blir så här (alla kommentarer borttagna) function varargout = plusminusnoglobal(varargin) %PLUSMINUS M-file for plusminusnoglobal.fig % PLUSMINUS, by itself,... % Begin initialization code - DO NOT EDIT... % End initialization code - DO NOT EDIT % Executes just before plusminus is made visible. function plusminus_openingfcn(hobject,... eventdata, handles, varargin) handles.counter = 0; % skapa nytt fält i handles handles.output = hobject; % Update handles structure p 10 (38) Staffan Romberger, CSC, KTH, 2010-11-21
guidata(hobject, handles); %!! % --- Outputs from this function are returned to the command line. function varargout = plusminus_outputfcn... (hobject, eventdata, handles) varargout{1} = handles.output; % --- Executes on button press in pushbutton1. function pushbutton1_callback... (hobject, eventdata, handles) handles.counter = handles.counter+1 set(handles.text2,'string',num2str(handles.counter)); guidata(hobject, handles); %!! % --- Executes on button press in pushbutton2. function pushbutton2_callback(hobject, eventdata, handles) p 11 (38) Staffan Romberger, CSC, KTH, 2010-11-21
handles.counter = handles.counter - 1; set(handles.text2,'string',num2str(handles.counter)); guidata(hobject, handles); %!! % --- Executes on button press in pushbutton3. function pushbutton3_callback... (hobject, eventdata, handles) close all clear all p 12 (38) Staffan Romberger, CSC, KTH, 2010-11-21
F6: Filhantering (kap. 8) Läsning från tangentbordet, skrivning på skärmen Binär skrivning och läsning med save och load Skrivning på och läsning från textfil med save och load Användning av filreferenser, öppna, stänga, filslut Binär skrivning och läsning med filreferens Skrivning och läsning med formatstyrning p 13 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Läsning, skrivning, tangentbord, skärm Det finns många sätt att hämta och spara data. In från tangentbordet: med tilldelningskommando input(ledtext), input(ledtext,'s') Ut på skärmen: kommando utan ; variabelns namn skrivs också ut disp(uttryck) inget variabelnamn, char utan fprintf(formatsträng,uttryck, ) hur uttryckens värden skrivs styrs av formatkoderna. i formatsträngen p 14 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Tabell på skärmen Skriv en tabell med rätvinkliga trianglar med heltalssidor <= 100. fprintf('\n a b c\n'); for c=1:100 c2 = c^2; for a=1:floor(sqrt(c2/2)) a2 = a^2; b = round(sqrt(c2-a2)); if a2+b^2==c2 fprintf('%5d%5d%5d\n',a,b,c); end end end p 15 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Tabell på skärmen, test Resultatet är monterat i 3 kolumner: a b c 16 30 34 3 4 5 21 28 35 6 8 10 12 35 37 5 12 13 15 36 39 9 12 15 24 32 40 8 15 17 9 40 41 12 16 20 27 36 45 7 24 25 14 48 50 15 20 25 30 40 50 10 24 26 24 45 51 20 21 29 20 48 52 18 24 30 28 45 53 0 33 44 55 40 42 58 36 48 60 11 60 61 16 63 65 25 60 65 33 56 65 39 52 65... 28 96 100 60 80 10 p 16 (38) Staffan Romberger, CSC, KTH, 2010-11-21
save Ut på fil: save filnamn.suffix [variabellista] binärt till filen filnamn.suffix save [variabellista] alla variabler i arbetsplatsen (eller angivna) binärt till filen matlab.mat save filnamn [variabellista] binärt till filen filnamn.mat save filnamn.suffix [variabellista] -ascii [-double] [-tabs] som text till filen filnamn.suffix med 8 siffror, -double ger 16 siffror, -tabs ger tabulatorseparerad utskrift save -ascii [-double] [-tabs] som text till filen matlab.mat save filnamn [variabellista] -ascii [-double] [-tabs] som text till filen filnamn.mat p 17 (38) Staffan Romberger, CSC, KTH, 2010-11-21
load In från fil: load filnamn.suffix [variabellista] [-ascii -mat] alla variabler (eller angivna) från filnamn.suffix värdena läses normalt binärt, med -ascii eller med suffix annat än mat: alla data till variabeln filnamn (då används ej variabellistan) från filen som text load [variabellista] alla variabler (eller angivna) från matlab.mat binärt load -ascii alla data från matlab.mat som text till variabeln matlab load filnamn [variabellista] alla variabler (eller angivna) från filnamn.mat binärt load filnamn -ascii alla data från filnamn.mat som text till variabeln filnamn Load forts. p 18 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Med >> type in.dat 2 3 4 5 6 6 7 får man >> load in.dat??? Error using ==> load; Number of columns on line 2 of ASCII file in.dat must be the same as previous lines. Om vi tar bort " 6". >> load in.dat >> in in= 2 3 4 5 6 7 p 19 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Struct (Posttabeller) kan bara sparas binärt eller som XML-fil. p 20 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Filreferenser Med en filreferens håller Matlab reda på filen, vad man får göra med den och var man jobbar i den. [filreferens, msg] = fopen(filnamn,tillstånd) Tillstånd kan vara 'r', 'r+', 'w', 'w+', 'a', 'a+'. Om öppningen misslyckas blir filreferens 1 och ett felmeddelande lagras i variabeln msg. Vanligast: filen hittas inte. fclose(filreferens) Ev. utskrift avslutas. Filen stängs. Om det går bra återsänds 0 annars 1. feof(filreferens) sant om inga data återstår (eof = end of file ) p 21 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Binär skrivning och läsning med filreferens Skrivning binärt med filreferens: fwrite(filreferens, uttryck, precision) där precision kan vara 'char', 'int16', 'float32' m.m. Läsning binärt med filreferens: [variabel,antal] = fread(filreferens, storlek, precision) antal är antalet lästa värden, storlek är ett tal, Inf eller [m n] och precision som ovan p 22 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Fileread fileread(filnamn) ger filens innehåll som en sträng. p 23 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Skrivning och läsning med formatstyrning Skrivning som text med filreferens: fprintf(filreferens, formatsträng, uttryck, ) Utelämnad filreferens = standard output = skärm s = sprintf(formatsträng, uttryck, ) Returnerar en sträng till s Läsning från textfil med filreferens: [variabel,antal] = fscanf(filreferens, formatsträng, storlek) texten i filen tolkas som värden enligt formatsträng [variabel,antal] = sscanf(sträng,formatsträng, storlek) läser från sträng rad = fgetl(filreferens) texten fram till radslut, om filen står vid radslut återsänds -1 eof rad = fgets(filreferens) texten fram till och med radslut, om filen står vid radslut återsänds -1 p 24 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Med >>type s.dat ab c def ger >>s = fscanf(fopen('s.dat'),'%c') s = ab c def >>abs(s) ans = 97 98 32 99 10 10 100 101 102 p 25 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Formatsträng En formatsträng består av formatkoder, specialtecken och annan text. En formatkod har formen %[ + 0][#.#]k. % och k måste sättas ut! - vänsterställ + sätt alltid ut tecken 0 fyll ut med inledande nollor #.# totalt antal tecken.antal siffror/antal decimaler c ett tecken d decimalt heltal e exponentform med e E exponentform med E f decimalbråk g kortaste av e och f G kortaste av E och f p 26 (38) Staffan Romberger, CSC, KTH, 2010-11-21
s teckensträng u decimalt heltal utan tecken Specialtecken är %% (representerar ett procenttecken), \' (apostrof), '' (apostrof), \\ (inverterat snedstreck), \f (sidmatning), \r (vagnretur), \b (blanktecken), \t (tabulatortecken), \n (ny rad). Uttrycken paras ihop med formatkoderna. När formatsträngen tar slut används den från början igen. När data tar slut används formatsträngen fram till nästa formatkod eller till sitt slut. Text och specialtecken skrivs ut resp. matchas mot tecknen i filen. p 27 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Läs, lagra och skriv en textfil. >>fr = fopen('findgear.m','r') fr = 3 >>t = fscanf(fr,'%c',inf); >>disp(t); function [m,n,finalgear] = findgear(gear,min,max)... end >>whos t Name Size Bytes Class t 1x865 1730 char array p 28 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Läs en nx3 numerisk matris från textfil. Fyll ut sista raden. >>type t.dat 1 2 3 4 5 6 7 8 9 10 >>fr = fopen('t.dat','r') fr = 3 >>t = fscanf(fr,'%d',inf); size(t) ans = [10 1] >>% Fyll sista raden >>t = reshape([t; zeros(mod(-numel(t),3),1)],3,[])' % mod([-12-11 -10],3) är [0 1 2] t = 1 2 3 4 5 6 7 8 9 p 29 (38) Staffan Romberger, CSC, KTH, 2010-11-21
10 0 0 Med uigetfile och uisetfile kan man öppna dialogrutor för att välja in- och utfil. Man bör kontrollera om läsning och skrivning gick bra: [felmed,felnr] = ferror(filreferens); if felnr~=0 disp(felmed); end p 30 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Funktion som parameter gjort F8 p 31 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Bankkontoregister för egen begrundan, F8 Vi har en posttabell, REG, med fälten: kontonummer, namn, ranta och saldo och en funktion saldo = trans(accountno, amount). Låt oss bygga ut hanteringen av detta register. Man kan bl.a. tänka sig följande kompletteringar: Skapa ett konto Ta bort konto Redigera konto, t.ex. namnbyte eller rättelse av fel Hantera ränta, ev. med särskild hantering av konton med underskott Låt oss börja med att ta bort ett konto. Funktionen kan ta kontonummer som inparameter, behöver inte returnera något, kan kommunicera med användaren och kan ha huvudet: function killaccount(accountno) Vi behöver göra det vi gjorde i trans, nämligen söka i registret efter en post med ett givet kontonummer. Då är det rimligt att göra funktionen p 32 (38) Staffan Romberger, CSC, KTH, 2010-11-21
regfind anropbar från både trans och killaccount. Vi flyttar alltså funktionen till en fil med namnet regfind.m: function index = regfind(accountno) % Sök en post i REG med kontonummer accountno % Returnera postens nummer % eller -1 om sådan post inte finns global REG for no = 1:numel(REG) if REG(no).kontonummer==accountno index = no; return; end end index = -1; I killaccount bör vi kontrollera indata, att det är en inparameter och att det är ett tal i tillåtet intervall. T.v. förutsätter vi att kontonummer ska ligga i intervallet 1..99 999. p 33 (38) Staffan Romberger, CSC, KTH, 2010-11-21
function killaccount(accountno) % Om accountno är ett tillåtet kontonummer och % det finns ett konto med detta nummer tas posten % med detta nummer bort ur REG global REG accountno = accountno(1); if ~isnumeric(accountno) error('kontonumret är ej ett tal.'); elseif mod(accountno,1) error('kontonumret är ej ett heltal.'); elseif accountno<1 accountno>99999 error(['kontonumret ligger ej mellan 1 '... 'och 99999.']); end recno = regfind(accountno); if recno==-1 error(['det finns inget konto med nummer '... p 34 (38) Staffan Romberger, CSC, KTH, 2010-11-21
num2str(accountno)]); else disp('ska följande konto dödas?'); disp(reg(recno)); answer = input('svara ''J'' för ja: ','s'); if upper(answer)=='j' REG(recno) = []; disp('kontot är dödat.'); else disp('kontot tas ej bort.'); end end Registret är ju globalt så att det nås från alla funktioner där det är deklarerat globalt. Det försvinner dock när man avslutar Matlab. Vi kan spara registret på fil med save REGfile REG som sparar variabeln REG på filen REGfile.mat så att den kan hämtas med load REGfile. p 35 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Härefter kan den intresserade studenten göra andra tillägg till bankkontohanteringen. p 36 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Avslutning av programmeringskursdelen Det finns mer i Matlab Ni kan fördjupa det ni redan har sett. Ni kan lära känna Matlabs verktygslådor. Ni kan lära er objektorienterad programmering med Matlab. Kursen fortsätter med Programmeringslaboration 3 Numeriska metoder inkl. laborationer Projektet Tentan Hur går du vidare? Använd Matlab i nummedelen och i andra kurser. Läs kursen Tillämpad datalogi (tilda). p 37 (38) Staffan Romberger, CSC, KTH, 2010-11-21
Matlab-program visade: fibo_rec.m ======== function F = fibo_rec(n) global TRACEON NCALLS NCALLS = NCALLS + 1; if n == 1 F = 1; elseif n == 2 F = 2; else F = fibo_rec(n-1)+fibo_rec(n-2); if TRACEON disp(['n-1: ',num2str(n-1),' n-2: ',num2str(n-2)]) end end p 38 (38) Staffan Romberger, CSC, KTH, 2010-11-21