Hlavní navigace

Cirkus s okny: třída wxFrame

Zdeněk Král

V dnešním pokračování o knihovně wxPython si budeme definovat naši vlastní třídu rodičovského okna a seznámíme se tak s třídou wxFrame jako výchozím prvkem pro tvorbu grafického rozhraní. Pomocí metod této třídy rozšíříme náš základní projekt o běžné prvky typu status bar, toolbar, kontextové nabídky a další.

V úvodu druhého dílu o wxPython bych rád zdůraznil, že se jedná o plně objektové GUI prostředí a podle toho se odvíjí i celková filozofie tvorby všech aplikací používajících wxPython. Základem každé aplikace je třída, která je potomkem mateřské třídy wxApp a dědí její metodu OnInit() . A právě tato metoda nám vytváří základní okno jako výchozí framework pro všechny své další potomky typu MDI Frame, vestavěná dialogová okna typu wxFileDialog… nebo uživatelská dialogová okna typu wxDialog atd.

01.  #!/usr/local/bin/env python
02.
03.  from wxPython import *
04.
05.  class MyApp(wxApp):
06.
07.      def OnInit(self):
08.          frame = wxFrame(NULL, -1, "Základní projekt")
09.          frame.Show(true)
10.          self.SetTopWindow(frame)
11.          return(true)
12.
13.  app = MyApp(0)
14.  app.MainLoop()

Na řádku 03. dochází k importu všech dostupných modulů z knihovny wxPython. Lze samozřejmě provést import pouze jednotlivých modulů, ale doporučuji tento plný import, abychom si nemuseli hlídat případné závislosti.

Pomocí děděné metoty třídy wxApp provedeme na řádku 09. zobrazení vlastního okna a metodou self.SetTopWindow() informujeme knihovnu o tom, že je toto okno hlavní oknem aplikace. Při ukončení tohoto okna dojde i k ukončení vlastní aplikace.

Na řádku 13. vytvoříme instanci třídy MyApp a zavoláme její metodu app.MainLoop(), která zajistí průběh nekonečné smyčky až do doby zavření hlavního okna aplikace.

Toto obecné schéma skriptu budeme používat prakticky ve všech aplikacích používajících jako GUI rozhraní právě knihovnu wxPython.

Přidání námi definované třídy hlavního okna:

01.  #!/usr/local/bin/env python
02.
03.  from wxPython import *
04.
05.  Title = "Projekt"
06.
07.  class MyFrame(wxFrame):
08.
09.      def __init__(self, parent, id, title):
10.
11.          wxFrame.__init__(self, parent, id,wxPoint(150,150),
12.                           wxSize(650, 400))
13.
14.          self.CenterOnScreen()

15.
16.  class MyApp(wxApp):
17.
18.      def OnInit(self):
19.          frame = MyFrame(NULL, -1, Title)
20.          frame.Show(true)
21.          self.SetTopWindow(frame)
22.          return(true)
23.
24.  app = MyApp(0)
25.  app.MainLoop()

Oproti předchozímu kódu se nám již aplikace rozrostla o námi definovanou třídu MyFrame, která dědí všechny vlastnosti třídy wxFrame.

Třída wxFrame:

Pro úplnost si uvedeme i předky této třídy, z kterých dědí důležité metody:

wxWindow, wxEvtHandler, wxObject

Defaultní konstruktor této třídy má následující formát :

wxFrame.__init__( parent, id, title, pos, size, style, name )

Parametry třídy wxFrame :

První čtyři parametry jsou povinné, zbývající volitelné,

  • parent má defaultně hodnotu NULL, v dalších případech budeme psát obecně self jako ukazatel na okno, v němž bude tento objekt obsažen.
  • id vyjadřuje identifikátor našeho okna, podle kterého se na něj můžeme odkazovat. Defaultně má hodnotu  –1 , v ostatních případech hodnotu typu integer .
  • pos určuje pozici okna na obrazovce pomocí třídy wxPoint(int, int). Defaultně má hodnotu (-1, –1) , v ostatních případech dle požadované pozice.
  • size určuje velikost okna pomocí třídy wxSize(int, int). Defaultně má hodnotu (-1, –1 ) , v ostatních případech dle požadované velikosti.
  • style nabývá následujících hodnot :
    • wxMAXIMIZE
    • wxMINIMIZE
    • wxICONIZE
    • wxSYSTEM_MENU
    • wxSIMPLE_BORDER
    • wxRESIZE_BORDER
    • wxSTAY_ON_TOP
    • wxDEFAULT_FRA­ME_STYLE , který v sobě zahrnuje defaultně styly wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BOX | wxSYSTEM_MENU | wxCAPTION
    Styly lze v zadání parametrů kombinovat pomocí znaku | , pokud neuvedeme v parametru žádný styl, bude použit defaultně wxDEFAULT_FRA­ME_STYLE a naše hlavní okno se bude chovat, jak jsme obecně v GUI zvyklí.
  • name určuje jméno okna a má význam pouze při používání knihovny Motif, osobně jsem tento parametr nikdy nepoužil.

Metody třídy wxFrame

Vyjmenuji zde pouze ty metody, které mají praktický význam pro náš seriál, jinak jich tato třída obsahuje mnohem více, ale nechci zde vytvářet doslovný překlad referenční příručky pro knihovnu wxWindow.

  • wxFrame.CreateS­tatusBar() nám vytvoří status bar při dolním okraji okna.
  • wxFrame.Create­ToolBar() obdobně vytvoří toolbar při horním okraji okna.
  • wxFrame.SetMe­nuBar() definuje zobrazení menu asociovaného k volajícímu oknu.
  • wxFrame.SetSta­tusWidths() definuje počet polí a jejich velikost ve status baru. Indexace polí je od 0…n u prvního pole a obráceně 0…-1 u posledního pole, jak jsme v pythonu obecně zvyklí.
  • wxFrame.SetSta­tusText() definuje text, který se nám po zobrazení okna objeví ve status baru. Zde platí stejná zásada pro indexaci polí.
  • wxFrame.SetTitle() nám umožňuje dle potřeby i za běhu aplikace měnit název hlavního okna.

Rozšíření projektu

A nyní v našem projektu použijeme výše popsané nové metody třídy wxFrame. Zkusíme hned něco praktického a přidáme si do status baru zobrazení aktuálního datumu a času. Přeci jenom, když se něco v okně hýbe, je to už zábavnější.

01.  #!/usr/local/bin/env python
02.
03.  from wxPython import *
04.  import time
05.
06.  Title = "Projekt"
07.
08.  class MyFrame(wxFrame):
09.
10.      def __init__(self, parent, id, title):
11.
12.          wxFrame.__init__(self, parent, id,wxPoint(150,150),
13.                           wxSize(650, 400))
14.
15.          self.CenterOnScreen()
16.
17.          sb = self.CreateStatusBar(2)
18.          sb.SetStatusWidths([-1, 130])
19.
20.          self.timer = wxPyTimer(self.Notify)
21.          self.timer.Start(1000)
22.          self.Notify()
23.
24.      def Notify(self):
25.
26.      t = time.localtime(time.time())
27.      st= time.strftime("%d-%b-%Y  %I:%M:%S", t)
28.      self.SetStatusText(st, 1)
29.
30.  class MyApp(wxApp):
31.
32.      def OnInit(self):
33.          frame = MyFrame(NULL, -1, Title)
34.          frame.Show(true)
35.          self.SetTopWindow(frame)
36.          return(true)
37.
38.  app = MyApp(0)
39.  app.MainLoop()

Na řádku 17. vytvoříme status bar o dvou polích a na řádku18. určíme šířku druhého pole, do kterého na řádku 28. umístíme námi požadované zobrazení aktuálního datumu a času.

A co nás čeká v příštím pokračování? Naučíme se vytvářet nabídky typu wxMenu a ukážeme si, jak naše aplikace rozpozná, pod kterým operačním systémem je spuštěna. Přidáme si i systémovou ikonu naší aplikace.

Našli jste v článku chybu?
20. 12. 2002 22:27
Zdeněk Král (neregistrovaný)

Musim podotknout, ze pouzivam prakticky pouze RedHat a SuSE. Na obou distribucich jsem experimentoval se zadavanim - #!/usr/bin/env python - ve vsech variantach, vcetne .../env python2, ale prave na distribucich RedHat do verze 7.1Cz i Us dochazi k chybam pri spousteni skriptu s wxPython, ktera se spatne linkuje ke skriptum.A zatim jsem mel vzdy bezproblemove spusteni prave s ".../local/bin/env" a vzdy doslo k nalinkovani wxPython. Nejsem na Linux jako OS zadny guru a zde uvadim pouze s…

19. 12. 2002 21:08
martin (neregistrovaný)

A kdyz uz jsme u toho shromazdovani chyb, #! /usr/local/bin/env python asi taky moc lidem fungovat nebude. Tahle konstrukce s env se pouziva kvuli tomu, ze nekde je python v /usr/bin, jinde v /usr/local/bin, ale env byva vsude /usr/bin/env (tento zmatek zacina uz v prvnim dile...) S tim spoustenim na rh7 bych to spis resil nalinkovanim ln python python2 (pokud uz neni) a #!/usr/bin/env python2 Ale kazdopadne diky za zajimavy serial