Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!
Zadejte Vaši e-mailovou adresu:
Kamarád fotí rád?
Přihlas ho k odběru fotomagazínu!
Zadejte e-mailovou adresu kamaráda:
Software
Kterak nakreslit modrý obdélník...
24. října 2006, 00.00 | V minulém dílu našeho volného seriálu o programování ve vývojovém prostředí Cocoa jsme se pustili do implementace vlastních podtříd NSView; popsali jsme si základní strukturu a principy, a slíbili jsme si, že se dnes trochu blíže podíváme na hlavní a primární vlastnost "views" – totiž vykreslení jejich obsahu.
V minulém dílu našeho volného seriálu o programování ve vývojovém prostředí Cocoa jsme se pustili do implementace vlastních podtříd NSView; popsali jsme si základní strukturu a principy, a slíbili jsme si, že se dnes trochu blíže podíváme na hlavní a primární vlastnost "views" – totiž vykreslení jejich obsahu.
Metoda drawRect:
Už minule jsme si řekli, že základem vlastního kreslení je metoda drawRect:, a že základní princip funguje takto: je-li zapotřebí nějaké "view" překreslit, toto "view"
- nejprve nastaví souřadnou soustavu tak, aby odpovídala jeho atributu "bounds" – tedy jeho vlastním souřadnicím, jež mohou být oproti ostatním "views" transformované –, a pak pošle samo sobě zprávu drawRect:;
- pak view postupně předá požadavek na překreslení všem svým podřízeným "views", jež udělají totéž.
Je tedy zřejmé, že vlastní vykreslení obsahu "view" je právě obsahem metody drawRect:. Dnes si toho o ní řekneme malinko více: je deklarována takto:
-(void)drawRect:(NSRect)rect;
přičemž argument rect označuje obdélník, jehož obsah je zapotřebí překreslit. Programátor toho může využít pro optimalizaci, a přeskočit jakékoli kreslicí příkazy, jejichž efekt by se projevil pouze mimo tento obdélník.
Naopak ale není v žádném případě povinné se na daný obdélník omezit! Každé "view" standardně před voláním metody drawRect: nastaví "clipping" – tedy omezení prostoru, do nějž lze kreslit – právě na ten obdélník, jenž pak předá metodě drawRect: jako její atribut. Jinými slovy, programátor si může dovolit argument zcela ignorovat, a kreslit kamkoli cokoli; framework se postará o to, aby byl vykreslen pouze zadaný obdélník.
Základy práce s barvami
Dříve, než si ukážeme nějaké příklady implementace metody drawRect:, se musíme podívat na aspoň nejzákladnější příkazy pro nastavení atributů kreslení. Později si ukážeme, že takovýchto atributů je řada a k většině z nich máme přístup prostřednictvím třídy NSGraphicsContext; prozatím nám však stačí to nejjednodušší – nastavení požadované barvy.
Na to potřebujeme dva kroky: nejprve musíme potřebnou barvu – v prostředí Cocoa tedy objekt třídy NSColor – nalézt; pak musíme vědět, kterak grafickému subsystému dát na vědomí, že právě tuto barvu chceme používat nadále pro kreslení.
My si nejprve ukážeme ten druhý krok, protože je jednodušší: stačí libovolné barvě (instanci třídy NSColor) poslat standardní zprávu set. Od té chvíle, dokud nepošleme zprávu set jiné barvě, nebo dokud nepoužijeme jinou službu pro změnu atributů grafického subsystému, se bude pro kreslení používat právě tato barva:
NSColor *color=....; [color set]; // od této chvíle kreslíme barvou "color"
A jak barvu získat? Nejjednodušší jsou třídní metody typu whiteColor, blackColor, blueColor a podobně, jež nabízejí přístup k základním, nejčastěji užívaným barvám – chceme-li kreslit třeba zeleně, stačí tedy provést příkaz
[[NSColor greenColor] set];
Seznam všech takovýchto metod nalezneme v dokumentaci třídy NSColor.
Kromě toho můžeme požadovanou barvu určit také prostřednictvím jejích složek. Máme k dispozici metody, využívající různé barevné prostory (zájemci je opět všechny naleznou v dokumentaci třídy NSColor); nejběžnější však rozhodně je barevný prostor RGB, a právě na něm si ukážeme příklad: odpovídající služba se jmenuje colorWithCalibratedRed:green:blue:alpha::
NSColor *color=[NSColor colorWithCalibratedRed:1 green:0 blue:0 alpha:1]; [color set]; // od této chvíle kreslíme červeně
Jednotlivé barevné složky mohou nabývat hodnot z intervalu 0-1; chceme-li právě poloviční intensitu, použijeme hodnotu 0.5. Designéři webových stránek jsou zvyklí na daleko hrubší paletu, určenou celočíselnými hodnotami z intervalu 0-255; je zřejmé, že dostaneme-li popis barvy v této podobě, snadno ji převedeme na naši pomocí dělení:
[NSColor colorWithCalibratedRed:r/255. green:g/255. blue:b/255. alpha:1];
Samostatný odstavec je vhodné věnovat složce alfa: ta vyjadřuje průhlednost (lépe řečeno neprůhlednost; alfa určuje míru, v níž daná barva odráží světlo). Mac OS X totiž plně a bez omezení dokáže pracovat s průhlednými (či spíše průsvitnými) barvami: použijeme-li barvu se složkou alfa rovnou 0.5, barva bude poloprůhledná – z 50 % tedy bude vidět to, co je pod ní. Použili-li bychom barvu s hodnotu alfa rovnou nule, vůbec bychom ji neviděli.
Nejjednodušší kreslení
Nyní se již můžeme podívat na ty nejzákladnější služby pro vlastní kreslení. Základem je rozhodně vykreslení obdélníku; k tomu Mac OS X nabízí několik možností, z nichž nejsnazší a nejjednodušší je služba NSRectFill. Dejme tomu, že chceme mít "view", jež je celé jednolitě modré – pak můžeme jeho metodu drawRect: implementovat takto:
-(void)drawRect:(NSRect)rect { [[NSColor blueColor] set]; NSRectFill([self bounds]); }
Výše uvedená implementace je zcela korektní a bude fungovat správně; je však zbytečně neefektivní: proč vybarvovat zbytečně kompletně celé pozadí našeho "view", pokud víme, že stačí překreslit pouze obdélník rect? Přesně stejně funkční, avšak o něco efektivnější implementace by mohla vypadat takto:
-(void)drawRect:(NSRect)rect { [[NSColor blueColor] set]; NSRectFill(rect); }
Je třeba ovšem zdůraznit, že v naprosté většině případů bude rozdíl zcela neměřitelný a nepodstatný, uvádíme oba příklady pouze pro lepší pochopení :)
Nadto je prvý přístup obvykle pohodlnější – to proto, že (ponecháme-li stranou jednolité pozadí celého "view") obvykle kreslíme ve vztahu k celé souřadné soustavě "view", tedy bounds, a nikoli pouze k právě překreslovanému obdélníku. Představme si, že chceme vykreslit jednoduché "view", vypadající nějak takto:
Je zřejmé, že toho můžeme docílit kupříkladu takto – využijeme-li standardních funkcí NSWidth a NSHeight, jejichž význam je zřejmý, a standardní funkce NSInsetRect, jež vygeneruje nový obdélník, na každé straně zúžený o hodnotu druhého a snížený o hodnotu třetího argumentu (tyto funkce bychom mohli přesnadno implementovat sami; využití standardních funkcí je však o něco málo efektivnější, a mnohem čitelnější :))
-(void)drawRect:(NSRect)rect { NSRect rr=[self bounds]; [[NSColor blueColor] set]; NSRectFill(rr); rr=NSInsetRect(rr,NSWidth(rr)/4,NSHeight(rr)/4); [[NSColor whiteColor] set]; NSRectFill(rr); }
Zde bychom již rect použít nemohli (přesněji řečeno, mohli, ale pouze v prvém příkazu NSRectFill, nikoli již ve druhém) – jinak bychom dostali zcela nesmyslný výsledek, v závislosti na v podstatě náhodné překreslované oblasti by se nám mohl bílý obdélník přemísťovat takřka "kamkoli".
Je vše zatím zřejmé? Ano-li, výborně! Ne-li, napište do diskuse... příště budeme pokračovat :)
Obsah seriálu (více o seriálu):
- Nastal čas na kakao...
- Tak nejdřív kakao ochutnáme...
- Programovací jazyk C: velmi, velmi stručně
- Objective C: to si vysvětlíme podrobněji
- Co jsme si o Objective C ještě neřekli...
- Nastal čas na kakao - Vznik a zánik objektů
- Nastal čas na kakao - Kopírování objektů
- Nastal čas na kakao - Skryté podtřídy
- Nastal čas na kakao - Základní služby objektů
- Nastal čas na kakao - Jak správně psát v Objective C
- Nastal čas na kakao - Jak správně importovat
- Nastal čas na kakao - Podtřídy, delegáti, vkládání, jak se to rýmuje?
- Nastal čas na kakao - Využití kategorií namísto dědičnosti
- Nastal čas na kakao - Vkládání objektů a přesměrování zpráv
- Nastal čas na kakao - Inicializace a rušení objektů
- Nastal čas na kakao - Metody initWith... a designovaný inicializátor
- Nastal čas na kakao - Inicializace: tipy a triky
- Nastal čas na kakao - Accesory: přístup k proměnným instancí
- Nastal čas na kakao - Šedá je teorie, zelený je strom života...
- Nastal čas na kakao - Více o XCode: inspektory
- Nastal čas na kakao - Aplikace RSS2: datový model
- Nastal čas na kakao - Aplikace RSS: implementace datového modelu
- Nastal čas na kakao - Aplikace RSS: parsování XML
- Nastal čas na kakao - Interface Builder a uživatelské rozhraní
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Druhý kontrolér a dokončení aplikace
- Nastal čas na kakao - Drobná vylepšení a zdokonalení...
- Nastal čas na kakao - Ladění
- Nastal čas na kakao - Třídy Foundation Kitu
- Nastal čas na kakao - Třídy Foundation Kitu (2)
- Nastal čas na kakao - Textové řetězce: NS(Mutable)String
- Nastal čas na kakao - Čísla, binární data a další...
- Nastal čas na kakao - Archivace objektů
- Nastal čas na kakao - Trocha magie, aneb distribuované objekty
- Nastal čas na kakao - Málem bychom zapomněli: NSAutoreleasePool
- Nastal čas na kakao - Zpracování výjimek: NSException
- Nastal čas na kakao - NSInvocation a černá magie
- Nastal čas na kakao - Kakao v Tygrovi
- Nastal čas na kakao - Notifikace: nepřímé předávání zpráv
- Nastal čas na kakao - NSUserDefaults
- Nastal čas na kakao - Co nového ve Foundation Kitu
- Nastal čas na kakao – s Intelem, s Intelem, jedeme do...
- Co nového v Xcode
- Začínáme s AppKitem
- Jak MVC v Kakau vypadá doopravdy?
- Jak MVC v Kakau vypadá doopravdy: dokončení
- Přehled tříd AppKitu
- Nastal čas na kakao - Přehled tříd AppKitu 2
- Přehled tříd AppKitu 3: zbývající třídy GUI
- Přehled tříd AppKitu 4: textový systém
- Nastal čas na kakao - Přehled tříd AppKitu 5: hlavně grafika
- Přehled tříd AppKitu 6: dokumentový systém
- Přehled tříd AppKitu 7: dokončení
- Pojmenované vlastnosti objektů
- Pojmenované vlastnosti objektů: implementace
- Pojmenované vlastnosti objektů: relace 1:N
- Pojmenované vlastnosti objektů: řazení jmen a agregační funkce
- Sledování změn objektů
- Sledování změn objektů – ukázka
- Sledování změn objektů – zdrojový kód
- Sledování změn objektů: kód modelu
- Sledování změn objektů: přímý přístup
- Kontroléry a vazby
- Vázání vazeb
- Další vazby s jednoduchým kontrolérem
- Implementace a použití převodu hodnot
- Validace hodnot
- Validace a chyby, a jedna hezká vazba...
- Práce s polem objektů
- Základní vazby NSArrayControlleru
- Převodníky, přepínače, placeholdery
- Mírná vylepšení v mezích zákona
- Objective C 2.0 - novinky z Leoparda
- NSTreeController
- Programování v Cocoa - Pár tipů a triků
- Programování v Cocoa - Základy kreslení
- Kterak nakreslit modrý obdélník...
- Další služby pro kreslení
- Obrázky a písmenka...
- Události a myš
- Lepší práce s myší
- Události klávesnice
- Input Management
- Příkazy a schránka
- Další události
- Táhni a padni
- Byli jsme na tahu; nyní padneme.
- Zvolme si, jak vhodit
- Drobnosti a chybičky
- Speciální případy tahání či házení
- Kterak táhnout něco, co neexistuje?
- Jak na sítě...
- NSURLConnection
- Safari za minutu
- Služby WebKitu
- Kakao v Leopardu
- Druhé Objective C
- Druhé Objective C: různé drobnosti
- Druhé Objective C: kategorie a protokoly
- Druhé Objective C: nový příkaz cyklu
- Druhé Objective C: atributy a accesory
- Druhé Objective C: atributy a accesory
- 64 je dvakrát 32
- Ubicumque dulce est, ibi et acidum invenies...
- Irbis: že prý žádné novinky?
- Blok sem, blok tam, nám už je to všechno jasné...
- Bloky jsou i v AppKitu
- Irbis a Foundation Kit
- Kde jsou má data?
- Kde jsou má data? V NSCache!
- Soubor, jméno, URL, jak se to rýmuje...
- Další podpora NSURL
- Zabíjení!
- A máme tady i...OS!
- Systémové prvky GUI
- Programování pro iOS 1. díl - Rozdíly mezi "i" a "Mac"
- Programování pro iOS - 2. Začínáme programovat
- Programování pro iOS - 3. základní ovladače a propojení GUI s kódem
- Programování pro iOS - 4. Varovná hlášení
- Programování pro iOS - 5. Rámce a jejich řídicí objekty
- Programování pro iOS - 6. Ukládání dat
- Programování pro iOS - 7. Správa paměti a starý restík
- Programování pro iOS - 8. Dokončení aplikace
- Programování pro iOS - 9. Jak dostat aplikaci do iPhone
- Programování pro iOS - 10. Instalace aplikace do cizího iPhone
- Programování pro iOS - 11. Jak dostat aplikaci do libovolného iPhone
- Programování pro iOS - 12. Touching!
- Programování pro iOS - 13. Kreslíme na iPhone
- Programování pro iOS - 14. Udělejme gesto
- Programování pro iOS - 15. Další gesta
- Programování pro iOS - 16. Více prstů, více zábavy
- Programování pro iOS - 17. Podpora standardních gest
- Programování pro iOS - 18. Recognizery v iOS
- Programování pro iOS - 19. Další standardní recognizery
- Programování pro iOS - 20. Co nového v iOSu
- Programování pro iOS - 21. "Multitasking"
- Programování pro iOS - 22. Nulla est honesta avaritia nisi temporis
- Programování pro iOS - 23. Jak se aktivovat, jsme-li v pozadí
- Programování pro iOS - 24. Zbývající drobnosti
- Programování pro iOS - 25. Řídicí objekty rámců
- Programování pro iOS - 26. Jak se dělá UIViewController
- Programování pro iOS - 27. Kde vzít rámce
- Programování pro iOS - 28. Základní služby
- Programování pro iOS - 29. Práce s rámci
- Programování pro iOS - 30. Rotace zařízení
- Programování pro iOS - 31. Správa paměti v rámcích
- Programování pro iOS - 32. Řídicí objekt pro tabulky
- Programování pro iOS - 33. Řídicí objekt pro strom
- Programování pro iOS - 33. Více o UINavigationControlleru
- Programování pro iOS - 35. Ještě jednou UINavigationController
- Programování pro iOS - 36. Po navigátoru taby
- Programování pro iOS - 37. Více o UITabBarControlleru
- Programování pro iOS - 38. Dokončení UITabBarControlleru
- Programování pro iOS - 39. UIPopoverController
- Programování pro iOS - 40. Další triky UIPopoverControlleru
- Programování pro iOS - 41. Zbývající služby UIPopoverControlleru
- Programování pro iOS - 42. UISplitViewController
- Programujeme v
iTunesXcode 4 - Programování pro iOS - 44. Předvolby Xcode 4
- Programování pro iOS - 45. Práce v Xcode 4
- Xcode 4: projekt a cíle
- Xcode 4: práce s cíli
- Xcode 4: Build Settings
- Xcode 4: Build Phases
- Xcode4: Build Phases podruhé
- Xcode 4: Co jsou to Build Rules?
- Xcode4: taje editoru
- Xcode4: automatické doplňování v editoru
- XIBy chyby
- Více o XIBech
- Editor XIBů
- Inspektory pro XIBy
- Vazby mezi objekty v XIBech
- Vazby mezi objekty v kódu
- Paletky Xcode pro XIBy
- Xcode 4: levý sloupec
- Xcode 4: okno Organizer
- Xcode 4: okno Organizer, část druhá
- Xcode 4: co je to Workspace?
- Xcode 4: základy schémat
- Xcode 4: akční schémata