wxPython je multiplatformní knihovna pro vytváření GUI aplikací. Pomocí wxPythonu tedy můžete vytvářet aplikace na Windows, Macu a různých UNIX-like systémech. wxPython je založen na wxWidgets, což je C++ knihovna. V prvním díle tohoto seriálu se naučíme, jak otevřít okno a pár dalších věcí.
Vítejte u překladu tutoriálu k wxPythonu. Originál najdete na stránce Zetcode.com.
Stažení a instalace
wxPython si můžete stáhnout na oficiálních stránkách. Vyberte si instalaci odpovídající vašemu operačnímu systému. K dispozici jsou vždy verze: unicode
a ansi
. Doporučuji stáhnout verzi unicode
, protože ta podporuje i jiné jazyky než angličtinu.
O instalaci se stará automatický instalátor, který sám najde cestu ke složce s pythonem. Jediné, co musíte udělat, je potvrdit, že souhlasíte s licencí. Funkčnost můžete vyzkoušet příkazem:
import wx
wxPython se skládá z pěti základních modulů:
Modul Controls poskytuje přístup ke všem základním komponentám, jako je wx.Button
, wx.NoteBook
nebo wx.ToolBar
. Modul Core obsahuje základní třídy wxPythonu. Mezi ně patří i třída wx.Object
, ze které dědí všechny ostatní třídy. Dále tam patří Sizery
, které se používají k rozmístění komponent po okně, události a další třídy jako wx.Point
nebo wx.Rectangle
. Graphics Device Interface (GDI) je množina tříd, které se starají o písmo, barvy, štětce nebo obrázky. Modul Misc – třídy určené pro logování, práci s obrazovkou nebo joystickem. Poslední modul, tedy Windows, obsahuje komponenty, které se nevešly do modulu Controls. Jedná se o komponenty, které samy o sobě nic nedělají, a jsou určeny k tomu, aby se do nich ostatní komponenty (z modulu Controls) umisťovaly. Je to tedy například wx.Frame
, wx.Panel
nebo wx.Dialog
.
Komponenty by se daly rozdělit do několika skupin.
- Základní komponenty
Tyto komponenty poskytují ostatním základní funkcionalitu. Obvykle se nepoužívají přímo. - Vysokoúrovňové komponenty
- Kontejnery
Kontejnery se používají k tomu, aby do sebe umisťovaly ostatní komponenty. Starají se tedy o grafické rozmístění prvků v okně. - Dynamické komponenty
Tyto komponenty může uživatel změnit (zmáčknout, napsat do nich text apod.). - Statické komponenty
Do těchto komponent se vykreslují informace pro uživatele. Uživatel je nemůže ovlivnit. - Ostatní komponenty
Do této skupiny patří menu, nástrojová lišta a statusbar.
První kroky
Začneme opravdu velmi lehkým příkladem. Náš první skript pouze otevře malé okno. Následuje zdrojový kód:
#-*- coding: utf-8 -*- import wx app = wx.App() frame = wx.Frame(None, -1, 'simple.py') frame.Show() app.MainLoop()
Nyní si vše vysvětlíme řádku po řádce:
import wx
Tato řádka importuje všechny základní moduly knihovny wxPython. Technicky vzato, všechny funkce modulu wx
jsou ve jmenném prostoru wx a proto budou přístupné pod prefixem wx.
. Následující řádka kódu vytváří základní objekt celé aplikace.
app = wx.App()
Každý program používající knihovnu wx musí vytvářet právě tento objekt.
frame = wx.Frame(None, -1, 'simple.py') frame.Show()
Vytvořili jsme objekt wx.Frame
. Jedná se o velmi důležitou komponentu. Do této komponenty budeme vykreslovat všechny další komponenty (je tedy rodičovskou komponentou). Jako rodičovskou komponentu objektu frame
jsme zvolili None
, což znamená, že frame
nemá žádného rodiče. Poté, co vytvoříme komponentu wx.Frame
, musíme zavolat metodu Show()
, abychom okno vykreslili na obrazovku.
app.MainLoop()
Poslední řádek pošle aplikaci do nekonečné smyčky. Tato smyčka zachytává všechny události a předává je naší aplikaci.
wx.Frame
Komponenta wx.Frame
je vůbec jedna z nejdůležitějších komponent wxPythonu. Jedná se o tzv. kontejner, což znamená, že mohou obsahovat vnořené komponenty (tlačítka, listboxy apod.).
wx.Frame
má následující konstruktor. Konstruktor se skládá ze sedmi parametrů, přičemž pouze první nemá přednastavenou hodnotu.
wx.Frame(wx.Window parent, int id=-1, string title='', wx.Point pos = wx.DefaultPosition, wx.Size size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE, string name = "frame")
Mezi parametry konstruktoru komponenty wx.Frame
patří style
. Tímto parametrem můžeme ovlivňovat, jak bude okno vypadat. Můžeme například schovat tlačítko pro zavření okna apod.
Standardní nastavení parametru style
je wx.DEFAULT_FRAME_STYLE
. Je to množina následujících vlastností: wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN
. Následuje krátký příklad.
import wx app = wx.App() window = wx.Frame(None, style=wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) window.Show(True) app.MainLoop()
Naším záměrem bylo vytvořit okno bez tlačítka pro schování okna. Proto jsme tento styl neuvedli v konstruktoru.
Velikost a pozice
Velikost můžeme specifikovat dvěma různými způsoby. Jednak máme v
konstruktoru parametr size
, nebo můžeme použít metodu
SetSize()
.
import wx
class Size(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(250, 200))
self.Show(True)
app = wx.App()
Size(None, -1, 'Size')
app.MainLoop()
Nastavování velikosti se děje v následujícím řádku kódu
wx.Frame.__init__(self, parent, id, title, size=(250, 200))
V konstruktoru jsme nastavili šířku komponenty na 250px a výšku na 200px.
Podobně můžeme určit pozici naší aplikace na obrazovce. Standardně je
okno umístěno vlevo nahoře, ale toto může být jiné v závislosti na OS
nebo okenním manažeru. Některé okenní manažery prostě vykreslí okno
někde na obrazovce. My můžeme to, kde se okno na obrazovce
vykreslí, ovlivnit, protože, jak jste si jistě všimli, parametr
pos
je součástí konstuktoru wx.Frame
.
Metoda | Metoda |
Move(wx.Point point) | posune okno na danou pozici |
MoveXY(int x, int y) | posune okno na danou pozici |
SetPosition(wx.Point point) | nastaví pozici okna |
SetDimensions(wx.Point point, wx.Size size) | nastaví pozici a velikost okna |
import wx class Move(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title) self.Move((800, 250)) self.Show(True) app = wx.App() Move(None, -1, 'Move') app.MainLoop()
Může nastat situace, kdy budete chtít okno maximalizovat. K tomu už má
wxPython připravenou metodu: Maximize()
. Tato metoda posune
okno na pozici (0, 0)
a sama propočítá potřebnou velikost,
aby okno bylo maximalizované. Je zde ještě jedna speciální metoda, pomocí
které umístíte vaši aplikaci přesně doprostřed obrazovky. Tato metoda se
nazývá Centre
.
import wx class Centre(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title) self.Centre() self.Show(True) app = wx.App() Centre(None, -1, 'Centre') app.MainLoop()
Komunikace mezi komponentami
Je důležité vědět, jak mohou komponenty mezi sebou komunikovat v rámci jedné aplikace. Prostudujte si následující příklad.
import wx
class LeftPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = parent.GetParent().rightPanel.text
button1 = wx.Button(self, -1, '+', (10, 10))
button2 = wx.Button(self, -1, '-', (10, 60))
self.Bind(wx.EVT_BUTTON, self.OnPlus, id=button1.GetId())
self.Bind(wx.EVT_BUTTON, self.OnMinus, id=button2.GetId())
def OnPlus(self, event):
value = int(self.text.GetLabel())
value = value + 1
self.text.SetLabel(str(value))
def OnMinus(self, event):
value = int(self.text.GetLabel())
value = value - 1
self.text.SetLabel(str(value))
class RightPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
self.text = wx.StaticText(self, -1, '0', (40, 60))
class Communicate(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(280, 200))
panel = wx.Panel(self, -1)
self.rightPanel = RightPanel(panel, -1)
leftPanel = LeftPanel(panel, -1)
hbox = wx.BoxSizer()
hbox.Add(leftPanel, 1, wx.EXPAND | wx.ALL, 5)
hbox.Add(self.rightPanel, 1, wx.EXPAND | wx.ALL, 5)
panel.SetSizer(hbox)
self.Centre()
self.Show(True)
app = wx.App()
Communicate(None, -1, 'widgets communicate')
app.MainLoop()
V našem příkladě máme dva panely, pravý a levý. Levý obsahuje dvě tlačítka, v pravém je umístěn jeden popisek. Tlačítka v pravém panelu mění číslo v druhém panelu. Otázka je, jak předáme tlačítkům referenci na popisek?
Tento problém by byl triviální, pokud by komponenty byly pouze v jedné třídě. Ale co když tomu tak není? V takové situaci musíme získat referenci skrz rodiče.
panel = wx.Panel(self, -1) self.rightPanel = RightPanel(panel, -1) leftPanel = LeftPanel(panel, -1)
Všimněte si toho, že pravý panel musí být vytvořen dříve než levý. Je
to proto, že při vykonávání konstuktoru LeftPanel
už musí
existovat onen popisek, který se nachází v pravém panelu. Je to logické,
přece nemůžeme hledat referenci na ještě neexistující komponentu.
self.text = parent.GetParent().rightPanel.text
Odpověd je zde. Každá komponenta má rodiče. V našem případě je rodič
ten panel, do kterého vykreslujeme levý a pravý panel. Voláním metody
parent.GetParent()
získáme referenci na třídu
Communicate
. A tato třída má referenci na pravý panel
(self.rightPanel
) a konečně, pravý panel obsahuje referenci
na popisek.