Hlavní navigace

Vzhled aplikací v PyGTK

Michal Smrž

Již třetí díl seriálu, který vás učí používat PyGTK. Dnes si ukážeme, jak lze řadit prvky do struktur a tím vytvářet layout - vzhled našich aplikací. Konkrétně bude řeč o gtk.HBox(), gtk.VBox(), gtk.Table() a okrajově škrtneme i o gtk.Fixed(). Vše doplněno screenshoty a ukázkou kódu u gtk.Table().

Doba čtení: 6 minut

Přehled

Při návrhu layoutu, což je rozmístění prvků, si musíte okno rozdělit do jednotlivých sekcí a ty pak, v případě potřeby, do dalších sekcí. Nikde se nevyplňuje absolutní umístění. Pouze zadáváte, v které sekci, poté, co jste je dostatečně rozdělili, tento prvek má být. Jeho skutečné umístění udělá GTK sám a pokud to okolnosti vyžádají (změna obsahu a tím pádem velikosti prvků, uživatel si změnil téma vzhledu nebo velikost textu, roztažení/zmenšení okna apod.), sám prvky posune/přerovná tak, aby dodržely zamýšlený vzhled.

gtk.HBox()
Horizontální (vodorovný) box. Jakékoli prvky do něj umístíme budou řazeny vedle sebe vodorovně – od leva do prava.

gtk.VBox()
Vertikální (svislý) box. Jakékoli prvky do něj umístíme budou řazeny svisle – odshora dolů.

gtk.Table()
Tabulka. Pokud chcete mít několik prvků vyrovnané tak, jak jsou vyrovnaná políčka v tabulce, kombinace HBoxů a VBoxů není zrovna to nejlepší řešení. Vždy se vám budou rozcházet řádky nebo sloupce. Na to tu máme právě gtk.Table(). Ten nám umožní widgety řadit do tabulky a dá nám možnost vybrané widgety roztáhnout i přes několik políček, jak svisle, tak vodorovně.

gtk.Fixed()
Nedoporučovaný způsob. Zatímco u prvních tří určujete layout, zde jen absolutní umístění. Divím se, proč je tento nepružný způsob i se svými problémy na Windows tak hojně používán.
Stačí, abychom umístili nějaké prvky těsně vedle sebe a pak aplikaci předali někomu, kdo má vzhled systému trochu jiný, a překrývající se tlačítka či jiná selhání layoutu jsou na světě. Nebo si všimněte v druhém a prvním díle tohoto seriálu rozdílné velikosti tlačítek (a písma v nich) Linux/Windows. Zkrátka dokud nebude nejvyšší nouze vyhnutí, nepoužívejte to.

gtk.HBox() / gtk.VBox()

Popisovat budu pouze gtk.HBox(), protože screenshoty u něj vypadají lépe. Vše co si zde řekneme k HBoxu, platí i pro VBox. Metodicky jsou to naprosto stejné funkce, jen se liší směrem řazení prvků.

Vytvoření boxu
nas_hbox = gtk.HBox(homo­geneous=False, spacing=0)

homogeneous – Všechny sekce mají mít stejnou velikost = velikost největší sekce.
spacing – Rozestup sekcí v pixelech.

Příklady:
Pro přehlednost mám nastavený rámeček na 10px ( okno.set_border_width(10)).

nas_hbox = gtk.HBox()

gtk Hbox

Prvky mají velikost akorát, rozestup žádný.

nas_hbox = gtk.HBox(True, 5)

gtk true5

Prvky mají stejnou velikost – tlačítka jsou roztaženy na velikost editační linky, rozestup je 5px.

Balení prvků
nas_hbox.pack_star­t(child, expand=True, fill=True, padding=0)
nas_hbox.pack_en­d(child, expand=True, fill=True, padding=0)

pack_start/pac­k_end – Podle toho, zda chceme balit odleva/odshora = start, nebo odprava/odspodu = end.
child – Objekt, co chceme vložit, jediný povinný parametr.
expand – Zda se má sekce při roztažení HBoxu (pravděpodobně roztažení okna), roztahovat taktéž = True, nebo zůstat stejně velká = False.
fill – Vložený objekt má být roztažen přes celou sekci = True, má zůstat stejně velký a zvětšovat se budou pouze okraje = False.
padding – Okraje prvku (nevyplní tedy celou sekci) v pixelech.

Konflikty
 – Pokud všechny prvky budou mít nastaveno expand = False, bude tato možnost vyrušena, protože není definováno, co se má při roztažení boxu roztáhnout = roztáhne se všechno.
 – Pokud je v definici boxu homogeneous = True a některé sekce mají nastaveno expand = False, dostane přednost definice boxu a všechny prvky mají expand = True.

Příklady
Pro přehlednost mám nastavený rámeček na 10px ( okno.set_border_width(10)).

Zakáz vyplnění:
nas_hbox = gtk.HBox(True, 5)
  nas_hbox.pack_start(objekt, False, False)

gtk Hbox false

Sekce jsou stejně velké (přednost definice boxu, expand=False neplatí), jejich velikost určila nejširší editační linka. Tlačítka ale již nejsou roztažená (fill=False).

Roztahování prvku:
nas_hbox = gtk.HBox(False, 5)
nas_hbox.pack_start(tlacitko3, True)

gtk Hbox true

Pro tlačítko 3 jsem jako jediné zadal expand = True. Při vykreslení není nic vidět, ale po roztažení okna do šířky je vidět, že získaný prostor navíc získalo pouze a právě tlačítko 3.

gtk.Table()

Vytvoření tabulky
nase_tabulka = gtk.Table(rows=1, columns=1, homogeneous=Fal­se)

rows – Počet řádků.
columns – Počet sloupců.
homogeneus – Všechny políčka mají stejnou velikost, a to jak výšku, tak šířku = velikost největšího políčka.

Balení prvků
nase_tabulka.at­tach(child, left_attach, right_attach, top_attach, bottom_attach, xoptions=gtk.EX­PAND|gtk.FILL, yoptions=gtk.EX­PAND|gtk.FILL, xpadding=0, ypadding=0)

Při umísťování prvků se neoznačují čísla sloupců a řádků, ale čísla jejich oddělovacích linek. Ty se počítají z levého horního rohu od nuly. Více napoví následující obrázek.

Tabulka

child – Objekt, který chceme vložit.
left_attach – Číslo levé svislé čáry, které se bude dotýkat levý okraj námi vkládaného objektu.
right_attach – Číslo pravé svislé čáry, které se bude dotýkat pravý okraj námi vkládaného objektu. V případě, že objekt je jen v jednom políčku, je to left_attach+1.
top_attach – Číslo horní vodorovné čáry, které se bude dotýkat horní okraj námi vkládaného objektu.
bottom_attach – Číslo spodní vodorovné čáry, které se bude dotýkat spodní okraj námi vkládaného objektu. V případě, že objekt je jen v jednom políčku, je to top_attach+1.
xoptions / yoptions – Chování daného políčka tabulky při roztažení tabulky v ose x / y.

  • gtk.EXPAND – roztahuje políčko, při změně velikosti tabulky
  • gtk.FILL – roztahuje objekt, aby zabralo celý prostor políčka
  • gtk.SHRINK – tak na jeho význam jsem bohužel nepřišel.

Pokud chcete použít více parametrů, oddělte jej znakem „|“ (horní znak klávesy „\“), na pořadí nezáleží.
xpadding – Velikost mezery vlevo a vpravo okolo objektu v pixelech.
ypadding – Velikost mezery nahoře a dole okolo objektu v pixelech.

A kde je sakra spacing?
Dobrá otázka. Zde je to trochu zbytečně komplikované. Na nastavení rozestupu musíme použít dvě metody tabulky, a to
tabulka.set_row_spa­cings(spacing) – Mezera mezi řádky tabulky v pixelech.
tabulka.set_col_spa­cings(spacing) – Mezera mezi sloupci tabulky v pixelech.

Konflikty
 – Prvky sdílí stejné políčko (ať už přímo, nebo jej sdílejí svojí částí) – přednost ve vykreslení dostane dříve umístěný prvek.
 – Čáry zadané při vkládání widgetu jsou mimo tabulku uvedenou v definici – tabulka se sama rozšíří, aby požadavek splnila.

Příklad
Pro přehlednost mám nastavený rámeček na 10px ( okno.set_border_width(10)).
Tři tlačítka, dvě vedle sebe, třetí pod nimi, široké jako horní dvě dohromady. Rozestup mezi tlačítky je 5px.

#!/usr/bin/env python

import gtk

# Vytvoreni okna
okno = gtk.Window()
okno.set_border_width(10)
okno.connect("destroy", gtk.main_quit)

# Vytvoreni tlacitek
tlacitko1 = gtk.Button("Tlacitko 1")
tlacitko2 = gtk.Button("Tlacitko 2")
tlacitko3 = gtk.Button("Tlacitko 3")

# Vytvoreni a vyplneni tabulky
tabulka = gtk.Table(2, 2, True) # 2 radky, 2 sloupce a stejna velikost policek
tabulka.set_row_spacings(5)
tabulka.set_col_spacings(5)

tabulka.attach(tlacitko1, 0, 1, 0, 1) # prvni sloupec, prvni radek
tabulka.attach(tlacitko2, 1, 2, 0, 1) # druhy sloupec, prvni radek
tabulka.attach(tlacitko3, 0, 2, 1, 2) # prvni az druhy sloupec, druhy radek

# start
okno.add(tabulka)
okno.show_all()

gtk.main()
Taulka1

gtk.Fixed()

Vytvoření widgetu
nas_fixed = gtk.Fixed()

Balení prvků
nas_fixed.put(wid­get, x, y)

widget – Objekt, co chceme vložit.
x – X-ová souřadnice levého horního rohu.
y – Y-ová souřadnice levého horního rohu.

MIF18 tip v článku témata

Fixed se počítá, stejně jako tabulka, od levého horního rohu od nuly. První pixel má souřadnice 0, 0.
Widgety lze přesouvat pomocí metody move(widget, x, y).

Příště:
Doteď to bylo hodně o teorii, ovšem od příště naskočíme konečně trochu na praxi.

Našli jste v článku chybu?