wxPython - rozmístění komponent v okně
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

wxPython - rozmístění komponent v okněwxPython - rozmístění komponent v okně

 

wxPython - rozmístění komponent v okně

Google       Google       3. 11. 2008       29 376×

Dnes se naučíme rozmisťovat komponenty v okně absolutně (pomocí souřadnic) a pomocí sizerů. Představíme si wx.BoxSizer, wx.GridSizer, wx.FlexGridSizer a wx.GridBagSizer.

Typická aplikace se skládá z různých komponent. Tyto komponenty jsou nějakým způsobem rozmístěny v rodičovských kontejnerech. O toto rozmístění se musí starat programátor, tedy vy. V podstatě máte dvě možnosti:

  • absolutní pozicování
  • použití sizerů

Absolutní pozicování

Programátor musí přesně určit pozici a velikost každé komponenty, což je pochopitelně celkem náročné, a proto se upřednostňuje programování pomocí sizerů. Následuje několik důvodů, proč neprogramovat absolutně:

  • Když změníte velikost okna, tak se velikost ostatních komponent nezmění.
  • Změna písma může rozhodit vzhled aplikace.
  • Pokud se rozhodnete přidat někam nějakou komponentu, musíte opět přepočítat pozice ostatních komponent.

Samozřejmě mohou nastat situace, kdy je absolutní pozicování lepší než užití sizerů. Například v tomto tutoriálu, protože použití sizerů by některé ukázky udělalo zbytečně složité. Ale ve skutečném světe programátoři užívají sizery.

V následujícím příkladě máme kostru textového editoru. Pokud změníme velikost okna, tak se velikost objektu wx.TextCtrl nezmění.

import wx

class Absolute(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 180))
        panel = wx.Panel(self, -1)

        menubar = wx.MenuBar()
        file = wx.Menu()
        edit = wx.Menu()
        help = wx.Menu()

        menubar.Append(file, '&File')
        menubar.Append(edit, '&Edit')
        menubar.Append(help, '&Help')
        self.SetMenuBar(menubar)

        wx.TextCtrl(panel, -1, pos=(-1, -1), size=(250, 150))

        self.Centre()
        self.Show(True)

app = wx.App(0)
Absolute(None, -1, '')
app.MainLoop()

Komponentě wx.TextCtrl jsme nastavili šířku 250px a výšku 150px.

Používání sizerů

Můžeme si vybrat z několika druhů sizerů. Všechny si je ve zbytku článku popíšeme a ukážeme si, jak se používají.

  • wx.BoxSizer
  • wx.StaticBoxSizer
  • wx.GridSizer
  • wx.FlexGridSizer
  • wx.GridBagSizer
import wx

class Sizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 180))

        menubar = wx.MenuBar()
        file = wx.Menu()
        edit = wx.Menu()
        help = wx.Menu()

        menubar.Append(file, '&File')
        menubar.Append(edit, '&Edit')
        menubar.Append(help, '&Help')
        self.SetMenuBar(menubar)

        wx.TextCtrl(self, -1)

        self.Centre()
        self.Show(True)

app = wx.App(0)
Sizer(None, -1, '')
app.MainLoop()

Objekt wx.TextCtrl nyní mění svou velikost v závislosti na velikosti okna. Ale jak to? Vždyť jsme žádný sizer nepoužili. On má totiž wx.Frame jeden zabudovaný. Do tohoto zabudovaného sizeru se dá umístit pouze jedna komponenta a ta pak vyplní všechen možný prostor.

wx.BoxSizer

Pomocí sizeru můžeme rozmístit komponenty buď do sloupce, nebo do řádku. Navíc můžeme jeden sizer vkládat do druhého, což nám umožňuje vytvářet celkem komplexní layout.

box = wx.BoxSizer(integer orient)
box.Add(wx.Window window, integer proportion=0, integer flag = 0, integer border = 0)

Orientace může být buď vertikální (wx.VERTICAL), nebo horizontální (wx.HORIZONTAL). Vkládání komponent do sizerů se děje zavoláním metody Add(). Tato metoda přijímá 4 parametry.

Parametr proportion definuje poměr, podle kterého se změní velikost komponent. Lépe si to vysvětlíme na příkladu. Mějme tři tlačítka s parametrem proporion nastaveným na 0, 1 a 2. Tlačítko s proporion = 0 se nezmění vůbec. Tlačítko s proportion = 2 bude dvakrát větší než tlačítko s proportion = 1.

Pomocí parametru flag můžeme nastavit, jak se budou chovat komponenty uvnitř sizeru. Můžeme například nastavit okraje jednotlivých komponent. Pokud chceme přidat mezi komponenty nějakou mezeru, musíme nastavit parametr border a určit, kde se okraj zobrazí. Tedy například flag = wx.LEFT. Parametr flag může nabývat hodnot:

  • wx.LEFT
  • wx.RIGHT
  • wx.BOTTOM
  • wx.TOP
  • wx.ALL

Tyto možnosti můžeme kombinovat pomocí operátoru |: flag = wx.LEFT | wx.RIGHT.

import wx

class Border(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(250, 200))

        panel = wx.Panel(self, -1)
        panel.SetBackgroundColour('#4f5049')
        vbox = wx.BoxSizer(wx.VERTICAL)

        midPan = wx.Panel(panel, -1)
        midPan.SetBackgroundColour('#ededed')

        vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20)
        panel.SetSizer(vbox)
        self.Centre()
        self.Show(True)

app = wx.App()
Border(None, -1, '')
app.MainLoop()
vbox.Add(midPan, 1, wx.EXPAND | wx.ALL, 20)

V ukázce jsme vytvořili 20px okraj kolem panelu midPan. Tím, že jsme specifikovali parametr flag = wx.ALL, jsme vykreslili okraj na všechny čtyři strany.

Do parametru flag přibylo pro nás ještě neznámé nastavení: wx.EXPAND. Tím jsme nastavili, že se daná komponenta roztáhne do volného prostoru. Můžeme také nastavit zarovnání pomocí následujících parametrů:

  • wx.ALIGN_LEFT
  • wx.ALIGN_RIGHT
  • wx.ALIGN_TOP
  • wx.ALIGN_BOTTOM
  • wx.ALIGN_CENTER_VERTICAL
  • wx.ALIGN_CENTER_HORIZONTAL
  • wx.ALIGN_CENTER

Reálná ukázka

V předchozím příkladě jsme sice použili sizery, ale takovou aplikaci bychom asi nikdy nevytvářeli. Nyní si ukážeme použití sizerů na reálnějším příkladě.

import wx

class GoToClass(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(450, 350))
        panel = wx.Panel(self, -1)
        font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
        font.SetPointSize(9)
        vbox = wx.BoxSizer(wx.VERTICAL)

        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        st1 = wx.StaticText(panel, -1, 'Class Name')
        st1.SetFont(font)
        hbox1.Add(st1, 0, wx.RIGHT, 8)
        tc = wx.TextCtrl(panel, -1)
        hbox1.Add(tc, 1)
        vbox.Add(hbox1, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 10)

        vbox.Add((-1, 10))

        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        st2 = wx.StaticText(panel, -1, 'Matching Classes')
        st2.SetFont(font)
        hbox2.Add(st2, 0)
        vbox.Add(hbox2, 0, wx.LEFT | wx.TOP, 10)

        vbox.Add((-1, 10))

        hbox3 = wx.BoxSizer(wx.HORIZONTAL)
        tc2 = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
        hbox3.Add(tc2, 1, wx.EXPAND)
        vbox.Add(hbox3, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)

        vbox.Add((-1, 25))

        hbox4 = wx.BoxSizer(wx.HORIZONTAL)
        cb1 = wx.CheckBox(panel, -1, 'Case Sensitive')
        cb1.SetFont(font)
        hbox4.Add(cb1)
        cb2 = wx.CheckBox(panel, -1, 'Nested Classes')
        cb2.SetFont(font)
        hbox4.Add(cb2, 0, wx.LEFT, 10)
        cb3 = wx.CheckBox(panel, -1, 'Non-Project classes')
        cb3.SetFont(font)
        hbox4.Add(cb3, 0, wx.LEFT, 10)
        vbox.Add(hbox4, 0, wx.LEFT, 10)

        vbox.Add((-1, 25))

        hbox5 = wx.BoxSizer(wx.HORIZONTAL)
        btn1 = wx.Button(panel, -1, 'Ok', size=(70, 30))
        hbox5.Add(btn1, 0)
        btn2 = wx.Button(panel, -1, 'Close', size=(70, 30))
        hbox5.Add(btn2, 0, wx.LEFT | wx.BOTTOM , 5)
        vbox.Add(hbox5, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10)

        panel.SetSizer(vbox)
        self.Centre()
        self.Show(True)


app = wx.App()
GoToClass(None, -1, 'Go To Class')
app.MainLoop()

Na začátku jsme vytvořili jeden vertikální sizer, do kterého jsme pak umístili pět horizontálních sizerů.

vbox.Add(hbox3, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 10)

vbox.Add((-1, 25))

Už víme, jak nastavovat vzdálenost mezi komponentami pomocí parametru flag a border. Je zde ale jedno omezení. V metodě Add() sice můžeme nastavit okraj, ale ten bude pro všechny strany stejný. V našem příkladě jsme nastavili okraj nalevo a napravo 10px. Ale už nemůžeme nastavit okraj 25px směrem dolů. Pokud tedy potřebujeme různé velikosti okrajů, můžeme mezi komponenty vložit nějaký volný prostor: vbox.Add((-1, 25)).

Dialog Najít/Nahradit

Následuje ukázka již celkem komplexního designu.

import wx

class FindReplace(wx.Dialog):
    def __init__(self, parent, id, title):
        wx.Dialog.__init__(self, parent, id, title, size=(255, 365))

        vbox_top = wx.BoxSizer(wx.VERTICAL)
        panel = wx.Panel(self, -1)

        vbox = wx.BoxSizer(wx.VERTICAL)

        # panel1

        panel1 = wx.Panel(panel, -1)
        grid1 = wx.GridSizer(2, 2)
        grid1.Add(wx.StaticText(panel1, -1, 'Find: ', (5, 5)), 0,  wx.ALIGN_CENTER_VERTICAL)
        grid1.Add(wx.ComboBox(panel1, -1, size=(120, -1)))
        grid1.Add(wx.StaticText(panel1, -1, 'Replace with: ', (5, 5)), 0, wx.ALIGN_CENTER_VERTICAL)
        grid1.Add(wx.ComboBox(panel1, -1, size=(120, -1)))

        panel1.SetSizer(grid1)
        vbox.Add(panel1, 0, wx.BOTTOM | wx.TOP, 9)

        # panel2

        panel2 = wx.Panel(panel, -1)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)

        sizer21 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, 'Direction'), orient=wx.VERTICAL)
        sizer21.Add(wx.RadioButton(panel2, -1, 'Forward', style=wx.RB_GROUP))
        sizer21.Add(wx.RadioButton(panel2, -1, 'Backward'))
        hbox2.Add(sizer21, 1, wx.RIGHT, 5)

        sizer22 = wx.StaticBoxSizer(wx.StaticBox(panel2, -1, 'Scope'), orient=wx.VERTICAL)

        sizer22.Add(wx.RadioButton(panel2, -1, 'All', style=wx.RB_GROUP))
        sizer22.Add(wx.RadioButton(panel2, -1, 'Selected Lines'))
        hbox2.Add(sizer22, 1)

        panel2.SetSizer(hbox2)
        vbox.Add(panel2, 0, wx.BOTTOM, 9)

        # panel3

        panel3 = wx.Panel(panel, -1)
        sizer3 = wx.StaticBoxSizer(wx.StaticBox(panel3, -1, 'Options'), orient=wx.VERTICAL)
        vbox3 = wx.BoxSizer(wx.VERTICAL)
        grid = wx.GridSizer(3, 2, 0, 5)
        grid.Add(wx.CheckBox(panel3, -1, 'Case Sensitive'))
        grid.Add(wx.CheckBox(panel3, -1, 'Wrap Search'))
        grid.Add(wx.CheckBox(panel3, -1, 'Whole Word'))
        grid.Add(wx.CheckBox(panel3, -1, 'Incremental'))
        vbox3.Add(grid)
        vbox3.Add(wx.CheckBox(panel3, -1, 'Regular expressions'))
        sizer3.Add(vbox3, 0, wx.TOP, 4)

        panel3.SetSizer(sizer3)
        vbox.Add(panel3, 0, wx.BOTTOM, 15)

        # panel4

        panel4 = wx.Panel(panel, -1)
        sizer4 = wx.GridSizer(2, 2, 2, 2)
        sizer4.Add(wx.Button(panel4, -1, 'Find', size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, 'Replace/Find', size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, 'Replace', size=(120, -1)))
        sizer4.Add(wx.Button(panel4, -1, 'Replace All', size=(120, -1)))

        panel4.SetSizer(sizer4)
        vbox.Add(panel4, 0, wx.BOTTOM, 9)

        # panel5

        panel5 = wx.Panel(panel, -1)
        sizer5 = wx.BoxSizer(wx.HORIZONTAL)
        sizer5.Add((191, -1), 1, wx.EXPAND | wx.ALIGN_RIGHT)
        sizer5.Add(wx.Button(panel5, -1, 'Close', size=(50, -1)))

        panel5.SetSizer(sizer5)
        vbox.Add(panel5, 1, wx.BOTTOM, 9)

        vbox_top.Add(vbox, 1, wx.LEFT, 5)
        panel.SetSizer(vbox_top)

        self.Centre()
        self.SetClientSize(panel.GetBestSize())
        self.ShowModal()
        self.Destroy()


app = wx.App()
FindReplace(None, -1, 'Find/Replace')
app.MainLoop()

Než začneme programovat náš layout, bylo by dobré si situaci nakreslit na kus papíru. Věřte, občas to pomůže ;-). Pokud se podíváme na obrázek dialogu, je jasně vidět, že se celé okno skládá z pěti panelů.

Každý z nich bude nový objekt wx.Panel. Všech pět panelů je pod sebou, a proto použijeme jako hlavní sizer vertikální wx.BoxSizer. V kódu jsme také použili pro nás zatím neznámý sizer wx.GridSizer, který bude vysvětlen za chvíli. Použili jsme ho proto, že nám velmi zjednodušuje práci. wx.GridSizer vytvoří mřížku (v našem případě má mřížka velikost 2x2) a do každé buňky umístí jedno tlačítko. Pokud bychom nepoužili wx.GridSizer, museli bychom použít vertikální BoxSizer, do kterého bychom vložili dva horizontální sizery.

wx.GridSizer

Sizer wx.GridSizer rozdělí komponenty do tabulky. Každá buňka tabulky je stejně široká.

wx.GridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)

V konstruktoru musíme určit, kolik bude mít sizer řad a kolik sloupců. Pomocí parametrů vgap a hgap se nastavují mezery mezi jednotlivými buňkami.

Vše si ukážeme na následujícím kódu. Jedná se o kostru kalkulačky, což je skvělý příklad pro vysvětlení GridSizeru.

import wx

class GridSizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(300, 250))


        menubar = wx.MenuBar()
        file = wx.Menu()
        file.Append(1, '&Quit', 'Exit Calculator')
        menubar.Append(file, '&File')
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.OnClose, id=1)

        sizer = wx.BoxSizer(wx.VERTICAL)
        self.display = wx.TextCtrl(self, -1, '',  style=wx.TE_RIGHT)
        sizer.Add(self.display, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 4)
        gs = wx.GridSizer(4, 4, 3, 3)

        gs.AddMany( [(wx.Button(self, -1, 'Cls'), 0, wx.EXPAND),
            (wx.Button(self, -1, 'Bck'), 0, wx.EXPAND),
            (wx.StaticText(self, -1, ''), 0, wx.EXPAND),
            (wx.Button(self, -1, 'Close'), 0, wx.EXPAND),
            (wx.Button(self, -1, '7'), 0, wx.EXPAND),
            (wx.Button(self, -1, '8'), 0, wx.EXPAND),
            (wx.Button(self, -1, '9'), 0, wx.EXPAND),
            (wx.Button(self, -1, '/'), 0, wx.EXPAND),
            (wx.Button(self, -1, '4'), 0, wx.EXPAND),
            (wx.Button(self, -1, '5'), 0, wx.EXPAND),
            (wx.Button(self, -1, '6'), 0, wx.EXPAND),
            (wx.Button(self, -1, '*'), 0, wx.EXPAND),
            (wx.Button(self, -1, '1'), 0, wx.EXPAND),
            (wx.Button(self, -1, '2'), 0, wx.EXPAND),
            (wx.Button(self, -1, '3'), 0, wx.EXPAND),
            (wx.Button(self, -1, '-'), 0, wx.EXPAND),
            (wx.Button(self, -1, '0'), 0, wx.EXPAND),
            (wx.Button(self, -1, '.'), 0, wx.EXPAND),
            (wx.Button(self, -1, '='), 0, wx.EXPAND),
            (wx.Button(self, -1, '+'), 0, wx.EXPAND) ])

        sizer.Add(gs, 1, wx.EXPAND)
        self.SetSizer(sizer)
        self.Centre()
        self.Show(True)

    def OnClose(self, event):
        self.Close()

app = wx.App()
GridSizer(None, -1, 'GridSizer')
app.MainLoop()

Všimněte si, jak je vytvořená mezera mezi tlačítky Bck a Close. Jednoduše jsme tam vložili prázdný wx.StaticText. Takové triky jsou celkem časté.

Místo metody Add() jsme použili metodu AddMany(). Pokud najednou vkládáte více komponent do sizeru, ušetříte několik znaků.

AddMany(list items)

Komponenty se v sizeru zarovnají podle toho, v jakém pořadí byly přidány. Nejprve se zaplní první řádek, pak druhý atd.

wx.FlexGridSizer

Tento sizer je velmi podobný wx.GridSizeru. Také umisťuje komponenty do tabulky, ale je trochu přizpůsobivější. Všechny buňky ve wx.GridSizeru mají stejnou velikost. U wx.FlexGridSizeru je tomu jinak. Všechny buňky v rámci jednoho řádku mají stejnou výšku. Všechny buňky v rámci jednoho sloupce mají stejnou šířku. Ale všechny řádky a sloupce nemusejí mít nutně stejnou výšku a šířku.

wx.FlexGridSizer(int rows=1, int cols=0, int vgap=0, int hgap=0)

Parametry rows a cols určují, kolik bude mít tabulka řádků a sloupců. Pomocí parametrů vgap a hgap se dá nastavit mezera mezi jednotlivými buňkami.

import wx

class FlexGridSizer(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(290, 250))

        panel = wx.Panel(self, -1)

        hbox = wx.BoxSizer(wx.HORIZONTAL)

        fgs = wx.FlexGridSizer(3, 2, 9, 25)

        title = wx.StaticText(panel, -1, 'Title')
        author = wx.StaticText(panel, -1, 'Author')
        review = wx.StaticText(panel, -1, 'Review')

        tc1 = wx.TextCtrl(panel, -1)
        tc2 = wx.TextCtrl(panel, -1)
        tc3 = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)

        fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author), (tc2, 1, wx.EXPAND),
            (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])

        fgs.AddGrowableRow(2, 1)
        fgs.AddGrowableCol(1, 1)

        hbox.Add(fgs, 1, wx.ALL | wx.EXPAND, 15)
        panel.SetSizer(hbox)

        self.Centre()
        self.Show(True)

app = wx.App()
FlexGridSizer(None, -1, 'FlexGridSizer')
app.MainLoop()

Analýza kódu:

hbox = wx.BoxSizer(wx.HORIZONTAL)
...
hbox.Add(fgs, 1, wx.ALL | wx.EXPAND, 15)

Vytvořili jsme horizontální wx.BoxSizer, protože chceme nějak oddělit okraj okna od krajů komponent (v tomto případě je to 15px).

fgs.AddMany([(title), (tc1, 1, wx.EXPAND), (author), (tc2, 1, wx.EXPAND),
      (review, 1, wx.EXPAND), (tc3, 1, wx.EXPAND)])

Metoda AddMany() je stejná jako u wx.GridSizeru.

fgs.AddGrowableRow(2, 1)
fgs.AddGrowableCol(1, 1)

Třetí řádek a druhý sloupec jsme nastavili zavoláním metod AddGrowableRow() a AddGrowableCol() tak, že se roztáhnou, pokud se okno zvětší. První dva řádky tabulky se mohou roztahovat horizontálním směrem. Třetí řádek se může roztahovat oběma směry.

wx.GridBagSizer

Toto je nejsložitější sizer ze všech. Mnoho programátorů pokládá za příliš složité ho používat. Přesto se práce s ním dá celkem dobře naučit. Chce to vytvořit několik grafických návrhů, prostě si to zažít.

Přestože tento sizer tvoří tabulky, je zde několik rozdílů oproti wx.FlexGridSizeru. Tento sizer umožňuje v metodě Add() specifikovat do jaké buňky se má komponenta vložit. Lze také nastavit span, tedy kolik buněk bude komponenta zabírat.

wx.GridBagSizer(integer vgap, integer hgap)

Parametry vgap a hgap definují, jaká bude mezera mezi jednotlivými buňkami. Stejně jako u všech předchozích sizerů se komponenta přidává zavoláním metody Add().

Add(self, item, tuple pos, tuple span=wx.DefaultSpan, integer flag=0, integer border=0, userData=None)

Parametr pos je umístění komponenty ve virtuální tabulce (levý horní roh má souřadnice (0, 0)). Pomocí parametru span můžeme určit, přes kolik buněk se daná buňka roztáhne (pokud je span = (3, 2), tak se komponenta roztáhne přes 3 řádky a 2 sloupce). Parametry flag a border už byly vysvětleny.

Buňky mohou měnit svou velikost v závislosti na změně velikosti okna. Standardně to ale není nastavené. Toto nastavení se dá změnit pomocí dvou metod:

AddGrowableRow(integer row)
AddGrowableCol(integer col)

Dialog Přejmenovat

Náš první příklad bude velmi lehký, takže není třeba se bát, že byste něco nepochopili. Vytvoříme dialog Přejmenovat, který bude obsahovat jeden objekt wx.StaticText, jeden objekt wx.TextCtrl a dva objekty wx.Button.

import wx

class Rename(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(320, 130))

        panel = wx.Panel(self, -1)
        sizer = wx.GridBagSizer(4, 4)

        text = wx.StaticText(panel, -1, 'Rename To')
        sizer.Add(text, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        tc = wx.TextCtrl(panel, -1)
        sizer.Add(tc, (1, 0), (1, 5), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        buttonOk = wx.Button(panel, -1, 'Ok', size=(90, 28))
        buttonClose = wx.Button(panel, -1, 'Close', size=(90, 28))
        sizer.Add(buttonOk, (3, 3))
        sizer.Add(buttonClose, (3, 4), flag=wx.RIGHT | wx.BOTTOM, border=5)

        sizer.AddGrowableCol(1)
        sizer.AddGrowableRow(2)
        panel.SetSizerAndFit(sizer)
        self.Centre()
        self.Show(True)


app = wx.App()
Rename(None, -1, 'Rename Dialog')
app.MainLoop()

Analýza kódu:

text = wx.StaticText(panel, -1, 'Rename To')
sizer.Add(text, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

Text 'Rename to' se má umístit do levého horního rohu. Proto jsme určili, že pos = (0, 0).

tc = wx.TextCtrl(panel, -1)
sizer.Add(tc, (1, 0), (1, 5), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

Objekt wx.TextCtrl se má vykreslit na dalším řádku, tedy (1, 0), a má se roztáhnout přes pět buňek (horizontálním směrem).

sizer.Add(buttonOk, (3, 3))
sizer.Add(buttonClose, (3, 4), flag=wx.RIGHT | wx.BOTTOM, border=5)

Tlačítka jsme vykreslili do čtvrtého řádku. Třetí je prázdný - tvoří mezeru mezi vstupem a tlačítky. Tlačítko Ok jsme umístili do 4. sloupce a tlačítko Close do pátého. Všimněte si, že jsme větší okraj nastavili pouze jednou tlačítku, ale změnila se výška celého řádku.

sizer.AddGrowableCol(1)
sizer.AddGrowableRow(2)

Poslední věcí, kterou musíme udělat, je upravit dialog tak, aby se šířka vstupu měnila současně s velikostí okna. Proto jsme nastavili, že druhý sloupec a třetí řádek se bude roztahovat společně se změnou velikosti okna.

Open Resource

Následující příklad je trochu složitější. Vytvoříme dialog, který můžete najít v Eclipse IDE.

import wx

class OpenResource(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 500))

        panel = wx.Panel(self, -1)
        sizer = wx.GridBagSizer(4, 4)

        text1 = wx.StaticText(panel, -1, 'Select a resource to open')
        sizer.Add(text1, (0, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        tc = wx.TextCtrl(panel, -1)
        sizer.Add(tc, (1, 0), (1, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        text2 = wx.StaticText(panel, -1, 'Matching resources')
        sizer.Add(text2, (2, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        list1 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB)
        sizer.Add(list1, (3, 0), (5, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        text3 = wx.StaticText(panel, -1, 'In Folders')
        sizer.Add(text3, (8, 0), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5)

        list2 = wx.ListBox(panel, -1, style=wx.LB_ALWAYS_SB)
        sizer.Add(list2, (9, 0), (3, 3), wx.EXPAND | wx.LEFT | wx.RIGHT, 5)

        cb = wx.CheckBox(panel, -1, 'Show derived resources')
        sizer.Add(cb, (12, 0), flag=wx.LEFT | wx.RIGHT, border=5)

        buttonOk = wx.Button(panel, -1, 'OK', size=(90, 28))
        buttonCancel = wx.Button(panel, -1, 'Cancel', size=(90, 28))
        sizer.Add(buttonOk, (14, 1))
        sizer.Add(buttonCancel, (14, 2), flag=wx.RIGHT | wx.BOTTOM, border=5)

        help = wx.BitmapButton(panel, -1, wx.Bitmap('icons/help16.png'), style=wx.NO_BORDER)
        sizer.Add(help, (14, 0), flag=wx.LEFT, border=5)

        sizer.AddGrowableCol(0)
        sizer.AddGrowableRow(3)
        sizer.AddGrowableRow(9)
        sizer.SetEmptyCellSize((5, 5))
        panel.SetSizer(sizer)

        self.Centre()
        self.Show(True)

app = wx.App()
OpenResource(None, -1, 'Open Resource')
app.MainLoop()
sizer.AddGrowableRow(3)
sizer.AddGrowableRow(9)

Chceme mít oba wx.ListBoxy roztahovatelné.

Zdroj: http://zetcode.com/wxpython/layout/

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

3 názory  —  3 nové  
Hlasování bylo ukončeno    
0 hlasů
Google
Autor studuje na FIT ČVUT a je šéfredaktorem portálu Matematika pro každého.
Web    

Nové články

Obrázek ke článku Stavebnice umělé inteligence 1

Stavebnice umělé inteligence 1

Článek popisuje první část stavebnice umělé inteligence. Obsahuje lineární a plošnou optimalizaci.  Demo verzi je možné použít pro výuku i zájmovou činnost. Profesionální verze je určena pro vývojáře, kteří chtějí integrovat popsané moduly do svých systémů.

Obrázek ke článku Hybridní inteligentní systémy 2

Hybridní inteligentní systémy 2

V technické praxi využíváme často kombinaci různých disciplín umělé inteligence a klasických výpočtů. Takovým systémům říkáme hybridní systémy. V tomto článku se zmíním o určitém typu hybridního systému, který je užitečný ve velmi složitých výrobních procesech.

Obrázek ke článku Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Jak vést kvalitně tým v IT oboru: Naprogramujte si ty správné manažerské kvality

Vedení týmu v oboru informačních technologií se nijak zvlášť neliší od jiných oborů. Přesto však IT manažeři čelí výzvě v podobě velmi rychlého rozvoje a tím i rostoucími nároky na své lidi. Udržet pozornost, motivaci a efektivitu týmu vyžaduje opravdu pevné manažerské základy a zároveň otevřenost a flexibilitu pro stále nové výzvy.

Obrázek ke článku Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Síla týmů se na home office může vytrácet. Odborníci radí, jak z pracovních omezení vytěžit maximum

Za poslední rok se podoba práce zaměstnanců změnila k nepoznání. Především plošné zavedení home office, které mělo být zpočátku jen dočasným opatřením, je pro mnohé už více než rok každodenní realitou. Co ale dělat, když se při práci z domova ztrácí motivace, zaměstnanci přestávají komunikovat a dříve fungující tým se rozpadá na skupinu solitérů? Odborníci na personalistiku dali dohromady několik rad, jak udržet tým v chodu, i když pracovní podmínky nejsou ideální.

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý