Hlavní navigace

Screenlet a základní kreslení

17. 9. 2009
Doba čtení: 6 minut

Sdílet

V minulém díle jsme si ukázali, jak napsat první vlastní a funkční Screenlet. Dnes budeme v naší práci pokračovat a společně se naučíme, jak můžeme v našem Screenletu „malovat“ různé objekty či „napsat“ text. Pomůže nám to nejen v tom, abychom naši mini aplikaci dostali do solidního designového stavu.

Nejprve však chci reagovat na některé komentáře.

  • V tomto seriálu se chci zabývat tím,  jak psát Screenlety a nechci je podrobně popisovat. Seriál je zaměřený na lidi, kteří vědí, co to je – většinou stejně člověk, co neví, co to je, je dělat nebude. Proto úvod do Screenletů je takový, jaký je.
  • Neuvedl jsem v perexu, že to je pouze pro Gnome, protože pokud splňujete podmínku Compizu, tak to můžete mít i v KDE či jiném prostředí.
  • Screenlety jsou psány v Pythonu, v ničem jiném.
  • Někdo používá Conky, někdo zase Screenlety. Já se zde zabývám tím, jak takový Screenlet napsat.
  • __init__ se provádí úplně jako první (to je snad jasné), on_map až, když se Screenlet kompletně načte. Například z příkladu můžete obsah metody on_map dát do __init__ v tomto případě. Chtěl jsem poukázat, že tu tato metoda také je – ne vždy se vše dá (musí) strčit do konstruktoru.

Začneme jednoduchou ukázkou

Pokud si dobře vzpomenete, tak jsme vlastně už minule nakreslili jeden objekt a napsali text. Text nám říkal, kolik je hodin a ten grafický objekt byl vlastně pozadí, který jsme vykreslili pomocí metody draw_rectangle. Dnes se však budeme zabývat více kreslením.

V následující ukázce je změněna proměnná width z 200 na 220 pixelů. Ostatní zůstává stejné z minulého příkladu.

def on_draw( self, ctx ):
  if self.scale > 5:
    self.scale = 5
  ctx.save()
  ctx.scale( self.scale, self.scale )

  ctx.set_source_rgba( 1, 1, 1, 0.1 )

  self.draw_rounded_rectangle( ctx, 0, 0, 20, self.width, self.height, fill=False ) # ohraniceni
  self.draw_circle( ctx, 5, 5, self.height-10, self.height-10 ) # leve kolecko

  self.draw_circle( ctx, self.width-self.height+5, 5, self.height-10, self.height-10 ) # prave kolecko

  self.draw_triangle( ctx, self.width/2-10, self.height-12, 20, 10, fill=True ) # trojuhelnik dole uprostred

  foo = str( time.localtime()[3] ) + ':' + str( time.localtime()[4] ) + ':' + str( time.localtime()[5] )
  ctx.set_source_rgba( 1, 1, 1 )
  self.draw_text( ctx, 'Prave je '+foo, 45, 10, 'FreeSans', 12, self.width, 'center' )

  ctx.restore()

V této ukázce jsou hned nové 4 metody, které zatím neznáme, ale z názvu je nejspíš jasné, co dělají – kreslí. Je tu i metoda, která se též stará o kreslení, ale pouze o barvu. To je důležité upozornění – musíme vědět, jakou barvu máme nastavenou, abychom se vyvarovali problému, že kreslíme text stejnou barvou (a průhledností) jako pozadí – to by bylo nepříjemné.

V proměnné ctx je objekt cairo, který nám vše kreslí. My používáme metody ze Screenletů a ty využívají právě knihovnu cairo. O import se však starat nemusíme, pokud si nechceme vytvořit vlastní funkci, ve které tuto knihovnu budeme potřebovat.

set_source_rgba

Metoda, jak je určitě patrné, nastavuje barvu. Dnes si jen dodáme, jaké parametry obsahuje. První tři atributy jsou barvy po složkách RGB (Red, Green, Blue; Červená, Zelená, Modrá), přičemž rozmezí je od 0 do 1 a 1 je maximum (tedy 100%/255/FF). Poslední, čtvrtý, atribut je průhlednost, zde platí, že čím menší číslo, tím větší je průhlednost. Poslední atribut (tedy průhlednost) je nepovinný a defaultně je nastaven na hodnotu 1 (neprůhledný).

draw_rectangle

draw_rectangle( self, ctx, x, y, width, height, fill=True ) 

draw_rectangle se v dnešní ukázce sice nevyskytuje, ale vyskytuje se v minulé. Jak již název metody napovídá, půjde o kreslení obdélníku (čtverce), přičemž souřadnice nastavíme atributy x a y a velikost pomocí atributů width a height. Poslední atribut fill (který je defaultně True) nastavuje, zda obdélník vyplnit nebo nakreslit pouze rámeček. Nesmíme však zapomenout na první atribut ctx, kterým předáváme naši proměnnou ctx (tedy náš objekt  cairo).

draw_rounded_rectangle

draw_rounded_rectangle( self, ctx, x, y, rounded_angle, width, height, round_top_left=True, round_top_right=True, round_bottom_left=True, round_bottom_right=True, fill=True ) 

Tato metoda nám může nakreslit nějaký obdélník (čtverec) jako předešlá metoda, ale s oblými rohy. Vše je stejné, až na to, že mezi atributy souřadnice a rozměry přibyl atribut rounded_angle, který udává míru zaoblení. Dále přibyly atributy round_top_left, round_top_right, round_bottom_left a round_bottom_right, pomocí kterých můžete změnit zaoblení jednotlivých rohů.

draw_circle

draw_circle( self, ctx, x, y, width, height, fill=True ) 

Další metodu, kterou jsem v ukázce použil, je draw_circle, která se nám stará o kreslení kruhů. Tato metoda má stejné parametry jako draw_rectangle pro kreslení obdélníků, jen upozorním, že atributy pro souřadnice určují také levý horní roh, nikoliv střed kruhu.

draw_triangle

draw_triangle( self, ctx, x, y, width, height, fill=True ) 

Metodu draw_triangle nebudu extra popisovat, je stejná jako v případě draw_rectangle či draw_circle, jediný rozdíl je, že touto metodou budeme kreslit trojúhelníky.

draw_text

draw_text( self, ctx, text, x, y, font, size, width, allignment, weight=0, ellipsize=<enum PANGO_ELLIPSIZE_NONE of type PangoEllipsizeMode> ) 

A konečně poslední, asi nejčastěji používaná metoda draw_text. S ní vypisujeme text a jako první atribut je ctx, poté následuje text, který chceme vypsat, dále souřadnice (levého horního rohu) a nakonec atributy spojené s textem (snad netřeba rozebírat): font, size, widthallignment.

Poslední atribut je ellipsize, kterým určujeme, co se má stát, pokud je text dlouhý. Defaultně se nestane „nic“ a text se natáhne na další řádek, pokud tuto vlastnost nechceme, můžeme přidat tři tečky (…) na začátek, konec nebo střed řetězce. Volby, které můžete vložit, a co přesně dělají, naleznete například zde. Jen musíte pro tuto volbu importovat modul pango. Ještě ukážu ukázku vložení tří teček uprostřed řetězce, pokud je řetězec dlouhý:

self.draw_text( ctx, 'toto je velmi dlouhy retezec, ktery se do jednoho radku (220px) nevejde', 0, 10, 'FreeSans', 12, 220, 'center', ellipsize=pango.ELLIPSIZE_MIDDLE ) 

Výsledek

A výsledek dnešního snažení bude vypadat jako na následujícím obrázku.

Screenlety 2

Další grafické metody

Nakonec uvedu další metody, které můžete při vykreslení Screenletu použít. Jako za domácí úkol si některé vyzkoušejte.

Pro kreslení čar využijeme draw_line.

draw_line( self, ctx, start_x, start_y, end_x, end_y, line_width=1, close=False, preserve=False ) 

Občas se hodí nakreslit i nějaký obrázek. To provedeme metodou draw_image pro kreslení obrázku v původní velikosti nebo draw_scaled_image, pokud chceme obrázku změnit velikost. Jako atribut pix napíšeme úplnou cestu k obrázku. Pokud chceme vykreslit ikonu, tak tu je na to speciální funkce draw_icon. Jediná změna u draw_icon  je ta, že v atributu pix neuvádíme úplnou cestu k ikoně, ale pouze její název.

draw_image( self, ctx, x, y, pix )
draw_scaled_image( self, ctx, x, y, pix, w, h )
draw_icon( self, ctx, x, y, pix, width=32, height=32 )

Dále tu je metoda draw_rectangle_advanced, pomocí které nějaký ten obdélník nadefinujeme opravdu podrobně. Máme tu možnost definovat pozici, velikost i zda vyplnit či kreslit jen rámeček a navíc tu je možnost pomocí N-tice (tuple) nastavit jednotlivé zaoblení rohů (postupně levý horní, pravý horní, levý dolní a pravý dolní), nastavení rámečku (velikost či barvu pomocí N-tice opět jako RGB + průhlednost v rozmezí od nuly do jedničky) nebo také přidat stín (stejné možnosti jako v případě rámečku).

CS24_early

draw_rectangle_advanced( self, ctx, x, y, width, height, rounded_angles=( 0, 0, 0, 0 ), fill=True, border_size=0, border_color=( 0, 0, 0, 1 ), shadow_size=0, shadow_color=( 0, 0, 0, 0.5 ) )

V předchozí metodě jsme mohli udělat i stín, ten jde však udělat i samostatně, pomocí následujících metod. draw_shadow udělá klasický stín dokola souřadnic. draw_side_shadow udělá přechod – z průhledný do určené barvy (atributem col), atribut side určuje z jaké strany je úplně průhledná (0 vlevo, 1 vpravo, 2 nahoře, 3 dole). Poslední draw_quadrant_shadow tu nebudu detailně popisovat, podívejte se na její zdrojový kód v dokumentaci a jen prozradím, že se to dá použít v rozích jako rohové (kulaté / zaoblené) stíny.

draw_shadow(self, ctx, x, y, w, h, shadow_size, col)
draw_side_shadow(self, ctx, x, y, w, h, side, col)
draw_quadrant_shadow( self, ctx, x, y, from_r, to_r, quad, col) 

Příště

Opět trošku experimentujte a příště se u kreslení ještě pozastavíme a naučíme se kreslit pomocí bufferů.

Byl pro vás článek přínosný?

Autor článku