Trochu předběhnu (budeme se tomu věnovat v příštím díle) a ukážeme si, jak zhruba bude vypadat struktura tabulky v databázi sqlite (pomůže nám to k pochopení dnešního dílu).
Název položky | Typ |
---|---|
id | INTEGER PRIMARY KEY |
name | VARCHAR(200) |
address | TEXT |
phone | VARCHAR(100) |
VARCHAR(200) |
Návrh dialogu pro vkládání / editaci dat
Dialog určený pro vkládání / editaci dat by měl vypadat zhruba takhle:
Spusťme Boa Constructor, otevřeme aplikaci „/AddressBook/App1.py“ a přidáme nový „wx.Dialog“ (v horním „Toolbaru“ v paletě „New“ tlačítko () Spustíme „Designer panel“ () a jako první v „Inspectoru“ změníme položku „Name: dlgAddressBook“ a „Title: Address book“. V záložce „Props“ zvolíme „Icon:“, otevřeme soubor „myImgRes.py“a zvolíme „ico01“. Pomocí tažení, popř. numericky v Inspectoru, upravíme dialog na nějakou rozumnou velikost (doporučuji wx.Size(320, 211) a uložíme.
Opětovně spustíme „Designer panel“ () a vložíme jednotlivé komponenty:
Class: | Name: | Label: | Style: |
---|---|---|---|
wx.StaticText | stName | Name: | |
wx.TextCtrl | txName | ||
wx.StaticText | stAddress | Address: | |
wx.TextCtrl | txAddress | wx.TE_MULTILINE | |
wx.StaticText | stPhone | Phone: | |
wx.TextCtrl | txPhone | ||
wx.StaticText | stEmail | Email: | |
wx.TextCtrl | txEmail | ||
wx.Button | btConfirm | C&onfirm | |
wx.Button | btCancel | C&ancel |
Pohrajeme si se sizery (já jsem použil 3× „wx.FlexGridSizer“), nemělo by větší význam toto rozepisovat (zachází se s nimi podobně, jako v předchozích dílech), pro případné zájemce doporučuji prostudovat můj vzorový zdrojový kód.
Jako poslední zkontrolujeme / upravíme „Tab Order…“ (slouží k tomu, aby bylo možné přeskakovat mezi jednotlivými položkami pomocí klávesy „Tab“). Klikněme na „dlgAddressbook“ (zvolíme tento dialog) a pak klikneme pravým tlačítkem myši. Otevře se nám nabídka a v její spodní časti zvolíme položku „Creation/Tab order…“. V otevřeném dialogu upravíme položky následovně:
Dále pak vytvoříme události pro jednotlivá tlačítka:
Name: | wx.EVT_BUTTON |
---|---|
btConfirm | myConfirm |
btCancel | myCancel |
Ukončíme „Designer panel“ () a v „Editoru“ upravíme funkci myCancel
def myCancel(self, event):
event.Skip()
self.Close()
Provedeme lokalizaci (viz díl Resource soubory a i18n ve wxPythonu) a celé naše snažení uložíme. Nyní můžeme v klidu ukončit Boa Constructor.
Začínáme programovat
I když to v tomto případě není nutné, je dobré si zvyknout, že většinu kódu není vhodné psát přímo do vygenerovaného kódu s UI, ale využít k tomu potomků daných tříd, např. z důvodu, že chcete vytvořený formulář použít více než jednou s jiným kódem, apod. K tomu v tomto příkladu slouží podadresář „lib/“. V něm vytvoříme (prozatím) 4 soubory („__init__.py“, „MyFunction.py“, „MyFrame.py“ a „dlgAddressBook.py“)
Jako první upravíme v nějakém editoru soubor „lib/MyFunction.py“ (bude nám sloužit pro přístup k členským funkcím, které budeme využívat v různých místech našeho programu). V něm vytvoříme třídu „MyFunction“ a prozatím jednu členskou funkci „OpenMyDialog“. Tato funkce nám bude sloužit k otevírání dialogových oken. Výpis souboru lib/MyFunction.py
import wx
class MyFunction:
enc = 'utf-8'
def OpenMyDialog(self, mywin, param=""):
self.dlg = mywin
self.dlg.CenterOnScreen() # vycentruje dialog
self.val = self.dlg.ShowModal() # nastaví dialog jako modální
self.dlg.Destroy()
Dále upravíme soubor „lib/MyFrame.py“ v němž vytvoříme třídu „MyFrame“ který je potomkem dvou tříd („ui.MyFrame.MyFrame“ a „lib.MyFunction.MyFunction“). Upravíme konstruktor (členská funkce „__init__“) tak, aby přejímal i parametr „size“. Dále pak vytvoříme členskou funkci „MyGrid“, která přejímá parametry počet sloupců („cols“) a šířku sloupců („size“). Bude nám sloužit k nastavení sloupců v tabulce „grData“ se všemi potřebnými parametry.
Další členskou funkcí bude „InsertRecord“, která nám prozatím bude sloužit k zobrazení dialogu „dlgAddressBook“.
Obsah souboru lib/MyFrame.py
import wx
from wx import GetTranslation as _
import ui.MyFrame, lib.MyFunction
import os
class MyFrame( ui.MyFrame.MyFrame, lib.MyFunction.MyFunction ):
conn = ''
numrec = 0
myId = 0
def __init__( self, parent, size ):
self._init_ctrls(parent) # inicializujeme ui.MyFrame
# nastavime jmena a sirku sloupcu v tabulce grData
colName = [ _("Name"),_("E-mail"), _("Phone") ]
colSize = [ size-560, 250, 250 ]
self.MyGrid( colName, colSize )
def MyGrid(self, cols, size):
nr = len(cols) # počet sloupců
self.grData.CreateGrid(0, nr)
self.grData.SetRowLabelSize(30) # nastaví výšku labelu
for i in range(len(cols)):
self.grData.SetColLabelValue(i,cols[i])
self.grData.SetColSize(i,size[i])
self.grData.SetColLabelAlignment(wx.ALIGN_LEFT, wx.ALIGN_CENTRE)
return
def InsertRecord(self, event):
# Slouží k vkládání záznamů
event.Skip()
tmp = {}
tmp['Id'] = 0
tmp['conn'] = self.conn
tmp['typ'] = 'insert'
import lib.dlgAddressBook
dlg = self.OpenMyDialog( lib.dlgAddressBook.dlgAddressBook( None, tmp ) )
Nyní vytvoříme potomka třidy „dlgAddressBook“ (soubor „lib/dlgAddressBook.py“). Vytvoříme konstruktor (členská funkce „__init__“) tak, aby přejímal i parametry „param“ a prozatím jen měnil podle těchto parametrů titulek okna.
Obsah souboru lib/dlgAddressBook.py
import wx
from wx import GetTranslation as _
import ui.dlgAddressBook, lib.MyFunction
class dlgAddressBook( ui.dlgAddressBook.dlgAddressBook, lib.MyFunction.MyFunction ):
conn = ''
actId = 0
typ = 'insert'
def __init__(self, parent, param):
self.conn = param['conn']
self.typ = param['typ']
self._init_ctrls(parent)
if self.typ == 'edit':
self.SetTitle( _('Address Book - Edit record') )
self.actId = param['Id']
else:
self.SetTitle( _('Address Book - Insert record') )
Vzhledem k tomu, že u většiny aplikací budeme požadovat, aby šířka hlavního okna byla pokud možno přes celou obrazovku, upravíme jako poslední soubor „AddressBook/App1.py“ následujícím způsobem (nezapomeňte změnit „import ui.MyFrame“ na „import lib.MyFrame“ a „self.main = ui.MyFrame.create(None)“ na „self.main = lib.MyFrame.MyFrame( None, x-2 )“):
import lib.MyFrame
modules ={u'MyFrame': [0, '', u'ui/MyFrame.py'],
u'dlgAddressBook': [0, '', u'ui/dlgAddressBook.py'],
u'myImgRes': [0, '', u'ui/myImgRes.py']}
class BoaApp(wx.App):
def OnInit(self):
wx.InitAllImageHandlers()
x, y = wx.GetDisplaySize() # získá šířku a výsku obrazovky
self.main = lib.MyFrame.MyFrame( None, x-2 )
self.main.SetSize( [ x-2, y-30 ] ) # nastaví šířku okna
self.main.CenterOnScreen() # nastaví pozici okna na obrazovce
self.main.Show()
self.SetTopWindow( self.main )
return True
def main():
application = BoaApp(0)
application.MainLoop()
Timto pro dnešek končíme, v příštím díle se budeme věnovat propojení aplikace s databází „sqlite“. Jakož v předchozích dílech, tak i dneska jsem připravil zdrojové kódy.