Obrázky a písmenka... - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

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:

Soutěž

Sponzorem soutěže je:

IDIF

 

Jaký fotograf/ka získal/a cenu za nejpopulárnější příspěvek v Nikon Photo Contest?

V dnešní soutěži hrajeme o:

Seriály

Více seriálů



Software

Obrázky a písmenka...

2. listopadu 2006, 00.00 | Minule jsme si ukázali, jak používat služby třídy NSBezierPath pro kreslení obecných obrázků: pro většinu běžných případů tyto příkazy bohatě stačí. Nestačí ovšem tehdy, když chceme v rámci vlastního "view" kreslit text, nebo hotové obrázky: a právě to se naučíme v dnešním dílu našeho seriálu.

Minule jsme si ukázali, jak používat služby třídy NSBezierPath pro kreslení obecných obrázků – samozřejmě, že služby grafického subsystému Mac OS X toho dokáží ještě daleko více, než co jsme si ukázali, ovšem ty základy, s nimiž jsme se seznámili, pro většinu běžných případů bohatě stačí.

Nestačí ovšem tehdy, když chceme v rámci vlastního "view" kreslit text, nebo hotové obrázky: a právě to se naučíme v dnešním dílu našeho seriálu.

NSImage a obrázky...

Pro práci s takřka libovolnou grafikou nabízí Mac OS X služby standardní třídy NSImage; ty jsou poměrně bohaté a velmi pohodlné. NSImage dokáže načíst takřka libovolný grafický formát (Mac OS X dokonce standardně obsahuje unikátní podporu grafických filtrů, jež umožňují libovolné aplikaci seznam formátů, jimž třída NSImage rozumí, jakkoli rozšířit... ale to odbočuji); můžeme jejím prostřednictvím ověřit atributy obrázku – a vyžádat si i jeho vykreslení.

Načtení obrázku z disku je jednoduché, a stačí nám na ně jediný příkaz: prostě pošleme třídě NSImage zprávu, jíž si vyžádáme načtení obrázku z daného souboru – nebo dokonce z daného URL:

NSImage *img1=[[NSImage alloc] initWithContentsOfFile:filename];
NSImage *img2=[[NSImage alloc] initWithContentsOfURL:url];

Pokud grafické knihovny nedokáží formát obrázku zpracovat (nebo pokud je třeba zadaný soubor nečitelný, nebo URL nedosažitelné), služba prostě vrátí nil; jinak dostaneme hotovou instanci třídy NSImage. A s tou již se dá dělat řada věcí.

Z toho, co nás zajímá v rámci kreslení, je asi nejpodstatnější možnost zjistit velikost obrázku – k tomu slouží zpráva size; to se hodí v případě, kdy potřebujeme obrázek kupříkladu vycentrovat v rámci bounds našeho "view". Chceme-li naopak velikost obrázku měnit, je vhodné vyžádat si pro něj dynamické změny velikosti příkazem setScalesWhenResized:YES a pak požadovanou velikost určit příkazem setSize:.

Nyní již můžeme obrázek přímo uvnitř metody drawRect: nakreslit na požadované místo. K tomu použijeme metodu compositeToPoint:operation:; třída NSImage nabízí i řadu jiných možností, avšak tato je patrně nejjednodušší. Druhým argumentem je operace, jež určuje jak přesně se má obrázek vykreslit; nejobecnější z operací, jež Mac OS X podporuje – a skorem vždy vhodná – se jmenuje NSCompositeSourceOver.

Centrování obrázku do "view" by tedy kupříkladu mohlo vypadat nějak takto:

@interface MyView:NSView {
  NSImage *image;
}
@end
@implementation MyView
-initWithFrame:(NSRect)frame {
  if (!(self=[super initWithFrame:frame])) return nil;
  image=[[NSImage alloc] initWithContentOfFile:....];
  return self;
}
-(void)dealloc {
  [image release];
  [super dealloc];
}
-(void)drawRect:(NSRect)rect {
  // pozadí...
  NSRect rr=[self bounds];
  NSSize sz=[image size];
  [image compositeToPoint:
    NSMakePoint((NSWidth(rr)-sz.width)/2,(NSHeight(rr)-sz.height)/2)
    operation:NSCompositeSourceOver];
}
...
@end

Text a NSTextFieldCell

Pro práci s textem samozřejmě užíváme známé třídy NSString (nebo NSAttributedString, pokud text zahrnuje také informace o formátu). Mac OS X samozřejmě umožňuje tyto objekty přímo kreslit pomocí služeb drawAtPoint: nebo drawAtPoint:attributes: (to v případě obyčejného NSStringu, u nějž samozřejmě musíme doplnit grafické atributy – písmo, barvu, velikost – jimiž se má písmo vykreslit); tyto služby však jsou poměrně nepohodlné, a potřebujeme-li písmo třeba zalamovat do řádků, dá to spoustu práce.

My si proto ukážeme daleko pohodlnější a šikovnější způsob, kterak kreslit textové řetězce do našich "views": využití standardní třídy NSTextFieldCell.

Připomeňme si nejprve, co to vůbec jsou obecně "cells" – v jednom z předcházejících dílů našeho seriálu, v němž jsme si ukazovali celkovou strukturu tříd AppKitu, jsme si o nich řekli toto:

"vnitřek" objektů view je vždy samostatný objekt, který nepotřebuje plnou sílu celého view – dokáže jen nakreslit sám sebe.

To je ovšem docela přesně to, co nyní potřebujeme. Proto se – ve většině případů – pro kreslení textu vyplatí použít právě služeb třídy NSTextFieldCell; může to vypadat kupříkladu nějak takto:

@interface MyView:NSView {
  NSTextFieldCell *tfc;
}
@end
@implementation MyView
-initWithFrame:(NSRect)frame {
  if (!(self=[super initWithFrame:frame])) return nil;
  tfc=[[NSTextFieldCell alloc] initTextCell:@""];
  [tfc setDrawsBackground:NO];
  [tfc setTextColor:[NSColor blueColor]];
  [tfc setFont:[NSFont fontWithName:@"Helvetica" size:24]];
  [tfc setBordered:NO];
  [tfc setBezeled:NO];
  [tfc setWraps:YES];
  ...
  return self;
}
-(void)dealloc {
  [tfc release];
  [super dealloc];
}
-(void)drawRect:(NSRect)rect {
  // pozadí...
  [tfc setStringValue:...];
  [tfc drawWithFrame:[self bounds] inView:self]; 
}
...
@end

Standardní služby třídy NSTextFieldCell se automaticky postarají o korektní vykreslení textu se zvolenými atributy; můžeme se spolehnout, že text nepřeteče hranice zadaného obdélníka. Povšimněme si zvláště nastavení setWraps:YES – díky němu máme "zadarmo" i automatické přelámání textu do řádků, je-li to zapotřebí.

Pokud bychom naopak chtěli, aby text zůstal na jediném řádku, ale je-li příliš dlouhý, automaticky se nejen ořízl, ale dokonce zobrazil "..." na konci pokud (a jen pokud) došlo k vypuštění některých znaků, můžeme použít nastavení

  [tfc setLineBreakMode:NSLineBreakByTruncatingTail];

Dokonce máme k dispozici alternativní argumenty NSLineBreakByTruncatingHead a NSLineBreakByTruncatingMiddle, jež nadbytečné znaky vypustí ze začátku/zprostředka řetězce (a opět je nahradí "...").

Za samostatnou zmínku nakonec stojí ještě jedna metoda: chceme zjistit, kolik místa skutečně text zabral – třeba proto, abychom bezprostředně pod něj mohli nakreslit obrázek? Nic snazšího; stačí poslat naší instanci NSTextFieldCell zprávu cellSizeForBounds: (jejímž argumentem je ten obdélník, do nějž text kreslíme), a dostaneme zpět přesnou velikost "pokreslené" oblasti.

Samozřejmě, pro kreslení existuje předlouhá řada dalších fint a triků: mohli bychom se naučit kreslit text na křivku; mohli bychom si ukázat, kterak kreslit stíny a gradienty... to vše je ale zapotřebí poměrně málokdy. Prozatím tedy s kreslením obsahu skončíme, a příště se podíváme na druhý velmi důležitý aspekt "views" – totiž na jejich schopnost zpracovávat události.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Začínáme s  

 » Rubriky  » Software  

Poslat článek

Nyní máte možnost poslat odkaz článku svým přátelům:

Váš e-mail:

(Není povinný)

E-mail adresáta:

Odkaz článku:

Vzkaz:

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: