× Aktuálně z oboru

Vychází Game Ready ovladače pro Far Cry 5 [ clanek/2018040603-vychazi-game-ready-ovladace-pro-far-cry-5/ ]
Celá zprávička [ clanek/2018040603-vychazi-game-ready-ovladace-pro-far-cry-5/ ]

wxPython - menu a nástrojová lišta

[ http://programujte.com/profil/1835-jakub-vojacek/ ]Google [ ?rel=author ]       [ http://programujte.com/profil/11280-michal-kobelka/ ]Google [ ?rel=author ]       21. 10. 2008       30 299×

Ve druhém dílu seriálu o wxPythonu se naučíme, jak vytvářet menu a nástrojovou lištu (toolbar).

Vytváření MenuBaru

Menu je jedno z nejviditelnějších částí celé GUI aplikace. Zatímco v konzolových aplikacích si musíte pamatovat všechny příkazy, v menu naleznete všechny příkazy roztříděné do logických částí. K vytvoření menu potřebujeme tři komponenty: wx.MenuBar, wx.Menu a wx.MenuItem.

Vytvoření jednoduchého menu ve wxPythonu je opravdu jednoduché. Zabere to pouze několik řádek kódu.

import wx

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

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

        self.Centre()
        self.Show(True)

app = wx.App()
SimpleMenu(None, -1, 'simple menu example')
app.MainLoop()

Jako obvykle si kód rozebereme řádku po řádce.

menubar = wx.MenuBar()

Nejprve vytvoříme objekt wx.MenuBar.

file = wx.Menu()

Pak vytvoříme objekt wx.Menu.

file.Append(-1, 'Quit', 'Quit application')

Přidáme položku do menu. První parametr je id položky. Druhý parametr je popisek položky a třetí parametr je pomocný popisek, který se zobrazí ve statusbaru, pokud je položka vybrána. V tomto příkladě jsme nevyužili objekt wx.MenuItem. Tento objekt byl za nás vytvořen metodou Append(). Později se naučíme wx.MenuItem používat.

menubar.Append(file, '&File')
self.SetMenuBar(menubar)

Poté přidáme menu do menubaru. Znak & představuje klávesovou zkratku. Znak, který následuje po &, bude podtržený. Tímto způsobem je menu přístupné pod klávesovou zkratkou alt + F. Nakonec zavoláme metodu SetMenuBar(). Tato metoda vykreslí menubar do okna.

Ikony, zkratky a události

Na několika následujících řádkách vylepšíme náš předchozí příklad. Ukážeme si, jak jednotlivým položkám v menu přidat ikonu. Ikony dělají naši aplikaci atraktivnější pro oči uživatele a také jim pomáhají pochopit, co přesně daná položka dělá. Také si ukážeme, jak přiřazovat naší aplikaci klávesové zkratky. Klávesové zkratky mohou velmi urychlit uživatelům práci s aplikací. Jednou z nejpoužívanějších klávesových zkratek je Ctrl + s. Je daleko rychlejší zmáčknout kombinaci těchto kláves, než najet myší na menu, otevřít ho a kliknou na Uložit. Také se velmi stručně řekneme něco o událostech a o tom, jak je zachytit a zpracovat.

import wx

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

        menubar = wx.MenuBar()
        file = wx.Menu()
        quit = wx.MenuItem(file, 1, '&QuittCtrl+Q')
        quit.SetBitmap(wx.Bitmap('icons/exit.png'))
        file.AppendItem(quit)

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

        menubar.Append(file, '&File')
        self.SetMenuBar(menubar)

        self.Centre()
        self.Show(True)

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

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

Analýza kódu:

quit = wx.MenuItem(file, 1, '&QuittCtrl+Q')
quit.SetBitmap(wx.Bitmap('icons/exit.png'))
file.AppendItem(quit)

Pokud chceme přidat ikonku nějaké položce v menu, musíme už použít objekt wx.MenuItem (nevystačíme si tedy s metodou Apend()). Znak následující po & je klávesová zkratka. V tomto případě se tedy aplikace zavře, pokud uživatel stiskne kombinaci Ctrl + q. Ikonu definujeme pomocí metody SetBitmap().

Jelikož jsme položku menu vytvářeli pomocí objektu wx.MenuItem a ne pomocí metody Append(), musíme danou položku ještě do menu přidat. Děje se tak pomocí metody AppendItem().

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

Pokud klikneme na položku quit nebo stiskneme kombinaci kláves Ctrl + q, wxPython vygeneruje událost wx.EVT_MENU. My jsme této události přiřadili metodu self.OnQuit. Třetím parametrem metody Bind je id. Menubar bude mít totiž obvykle více než jednu položku a proto musí mít každá položka unikátní id. O událostech si řekneme více později.

Submenu

Každé menu může mít v sobě submenu (menu vnořené v menu). Tímto způsobem můžeme rozdělit podobné příkazy do jednotlivých skupin. Například můžeme položky Projekt, Editace a Vzhled vložit do submenu nazvaného Panely nástrojů. V rámci menu můžeme jednotlivé položky od sebe oddělit separátorem. Je běžná záležitost, že položky Nový soubor, Otevřít a Uložit jsou odděleny separátorem od položek Tisk nebo Zavřít. V následujícím příkladu si ukážeme, jak vytvořit submenu a jak vložit do menu separátor.

import wx

ID_QUIT = 1

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

        menubar = wx.MenuBar()

        file = wx.Menu()
        file.Append(-1, '&New')
        file.Append(-1, '&Open')
        file.Append(-1, '&Save')
        file.AppendSeparator()

        imp = wx.Menu()
        imp.Append(-1, 'Import newsfeed list...')
        imp.Append(-1, 'Import bookmarks...')
        imp.Append(-1, 'Import mail...')

        file.AppendMenu(-1, 'I&mport', imp)

        quit = wx.MenuItem(file, ID_QUIT, '&QuittCtrl+W')
        quit.SetBitmap(wx.Bitmap('icons/exit.png'))
        file.AppendItem(quit)

        self.Bind(wx.EVT_MENU, self.OnQuit, id=ID_QUIT)

        menubar.Append(file, '&File')
        self.SetMenuBar(menubar)

        self.Centre()
        self.Show(True)

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

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

Následuje analýza kódu:

file.AppendSeparator()

Separátor do menu vložíme pomocí metody AppendSeparator.

imp = wx.Menu()
imp.Append(-1, 'Import newsfeed list...')
imp.Append(-1, 'Import bookmarks...')
imp.Append(-1, 'Import mail...')

file.AppendMenu(-1, 'I&mport', imp)

Vytváření submenu je opravdu triviální záležitost. Nejprve vytvoříme objekt wx.Menu, do kterého vložíme požadované položky. Nakonec vložíme submenu do hlavního menu zavoláním metody AppendMenu().

Různé druhy menu

Existují tři druhy menu:

  • Normální menu
  • Zaškrtávací (check) menu
  • Přepínací (radio) menu
import wx

ID_STAT = 1
ID_TOOL = 2

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

        menubar = wx.MenuBar()
        file = wx.Menu()
        view = wx.Menu()
        self.shst = view.Append(ID_STAT, 'Show statubar', 'Show Statusbar', kind=wx.ITEM_CHECK)
        self.shtl = view.Append(ID_TOOL, 'Show toolbar', 'Show Toolbar', kind=wx.ITEM_CHECK)
        view.Check(ID_STAT, True)
        view.Check(ID_TOOL, True)

        self.Bind(wx.EVT_MENU, self.ToggleStatusBar, id=ID_STAT)
        self.Bind(wx.EVT_MENU, self.ToggleToolBar, id=ID_TOOL)




        menubar.Append(file, '&File')
        menubar.Append(view, '&View')
        self.SetMenuBar(menubar)

        self.toolbar = self.CreateToolBar()
        self.toolbar.AddLabelTool(3, '', wx.Bitmap('icons/quit.png'))
        self.toolbar.Realize()
        self.statusbar = self.CreateStatusBar()
        self.Centre()
        self.Show(True)

    def ToggleStatusBar(self, event):
        if self.shst.IsChecked():
            self.statusbar.Show()
        else:
            self.statusbar.Hide()

    def ToggleToolBar(self, event):
        if self.shtl.IsChecked():
            self.toolbar.Show()
        else:
            self.toolbar.Hide()

app = wx.App()
CheckMenuItem(None, -1, 'check menu item')
app.MainLoop()

Následuje analýza kódu:

self.shst = view.Append(ID_STAT, 'Show statubar', 'Show Statusbar', kind=wx.ITEM_CHECK)
self.shtl = view.Append(ID_TOOL, 'Show toolbar', 'Show Toolbar', kind=wx.ITEM_CHECK)

Pokud chceme do menu přidat položku typu „zaškrtávátka“, musíme specifikovat parametr kind = wx.ITEM_CHECK (standardní hodnota je wx.ITEM_NORMAL). Metoda Append vrací wx.MenuItem.

view.Check(ID_STAT, True)
view.Check(ID_TOOL, True)

Když se aplikace spustí, je vidět nástrojová lišta (toolbar) i statusbar. Proto musíme obě položky zaškrtnout zavoláním metody Check().

def ToggleStatusBar(self, event):
    if self.shst.IsChecked():
        self.statusbar.Show()
    else:
        self.statusbar.Hide()

Schováme nebo zobrazíme statusbar na základě toho, jestli je daná položka menu zaškrtnuta nebo ne. To zjistíme zavoláním metody IsChecked().

Kontextové menu

Kontextové menu je vlastně menu bez menubaru. Objeví se vždy tam, kde je potřeba. Znáte to například z webového prohlížeče Firefox. Když kliknete pravým tlačítkem na stránku, objeví se kontextové menu s nabídkami jako „Ukázat zdrojový kód“ apod. Následující kód ukazuje, jak takové menu vytvořit.

import wx


class MyPopupMenu(wx.Menu):
    def __init__(self, parent):
        wx.Menu.__init__(self)

        self.parent = parent

        minimize = wx.MenuItem(self, wx.NewId(), 'Minimize')
        self.AppendItem(minimize)
        self.Bind(wx.EVT_MENU, self.OnMinimize, id=minimize.GetId())

        close = wx.MenuItem(self, wx.NewId(), 'Close')
        self.AppendItem(close)
        self.Bind(wx.EVT_MENU, self.OnClose, id=close.GetId())


    def OnMinimize(self, event):
        self.parent.Iconize()

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


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

        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)

        self.Center()
        self.Show()

    def OnRightDown(self, event):
        self.PopupMenu(MyPopupMenu(self), event.GetPosition())


app = wx.App()
frame = ContextMenu(None, -1, 'context menu')
app.MainLoop()

Následuje analýza kódu:

class MyPopupMenu(wx.Menu):
    def __init__(self, parent):
        wx.Menu.__init__(self)

Vytváříme vlastní třídu, která dědí z wx.Menu. V této třídě definujeme dvě metody: OnClose a OnMinimize.

self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)

Pokud v okně klikneme pravým tlačítkem myši, zavoláme tím metodu OnRightDown(). K tomu používáme ovladač wx.EVT_RIGHT_DOWN.

def OnRightDown(self, event):
     self.PopupMenu(MyPopupMenu(self), event.GetPosition())

V metodě OnRightDown() voláme metodu PopupMenu. Tato metoda zobrazí kontextové menu. První parametr je menu, které se zobrazí, a druhý parametr je pozice, kde se kontextové menu objeví. Správně by se mělo objevit na aktuální pozici myši a tu získáme, pokud zavoláme metodu GetPosition().

Nástrojová lišta

Do menu se vkládá většina funkcí, které daná aplikace zvládne. Nástrojová lišta (Toolbar) poskytuje přístup k těm nejpoužívanějším.

CreateToolBar(long style=-1, int winid=-1, String name=ToolBarNameStr)

Abychom vytvořili nástrojovou lištu, musíme zavolat metodu CreateToolBar.

import wx

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

        toolbar = self.CreateToolBar()
        toolbar.AddLabelTool(wx.ID_EXIT, '', wx.Bitmap('../icons/exit.png'))
        toolbar.Realize()

        self.Bind(wx.EVT_TOOL, self.OnExit, id=wx.ID_EXIT)

        self.Centre()
        self.Show(True)

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


app = wx.App()
SimpleToolbar(None, -1, 'simple toolbar')
app.MainLoop()

Analýza kódu:

toolbar.AddLabelTool(wx.ID_EXIT, '', wx.Bitmap('../icons/exit.png'))

Tlačítka do nástrojové lišty přidáváme pomocí metody AddLabelTool.

toolbar.Realize()

Poté, co do nástrojové lišty přidáme všechny tlačítka, musíme zavolat metodu Realize. Tím vykreslíme nástrojovou lištu do okna.

self.Bind(wx.EVT_TOOL, self.OnExit, id=wx.ID_EXIT)

Ke zpracování události kliknutí na nástrojovou lištu se používá ovladač wx.EVT_TOOL.

Pokud chceme, aby naše aplikace měla dvě nástrojové lišty, musíme to udělat jinak:

import wx

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

        vbox = wx.BoxSizer(wx.VERTICAL)

        toolbar1 = wx.ToolBar(self, -1)
        toolbar1.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('../icons/new.png'))
        toolbar1.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('../icons/open.png'))
        toolbar1.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('../icons/save.png'))
        toolbar1.Realize()

        toolbar2 = wx.ToolBar(self, -1)
        toolbar2.AddLabelTool(wx.ID_EXIT, '', wx.Bitmap('../icons/exit.png'))
        toolbar2.Realize()

        vbox.Add(toolbar1, 0, wx.EXPAND)
        vbox.Add(toolbar2, 0, wx.EXPAND)

        self.Bind(wx.EVT_TOOL, self.OnExit, id=wx.ID_EXIT)

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

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


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

Vytvořili jsme dvě instance třídy wx.ToolBar a umístili jsme je do vertikálního boxu.

toolbar1 = wx.ToolBar(self, -1)
...
toolbar2 = wx.ToolBar(self, -1)

Doposud jsme vytvářeli horizontální nástrojové lišty, ale občas může nastat situace, kdy budeme chtít vytvořit vertikální lištu.

import wx

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

        toolbar = self.CreateToolBar(wx.TB_VERTICAL)
        toolbar.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('new.bmp'))
        toolbar.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('open.bmp'))
        toolbar.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('save.bmp'))
        toolbar.AddLabelTool(wx.ID_ANY, '', wx.Bitmap('quit.bmp'))

        toolbar.Realize()


        self.Centre()
        self.Show(True)

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


app = wx.App()
VerticalToolbar(None, -1, 'vertical toolbar')
app.MainLoop()

Analýza kódu:

toolbar = self.CreateToolBar(wx.TB_VERTICAL)

Vertikální lištu vytváříme pomocí stylu wx.TB_VERTICAL.

V následujícím příkladu si ukážeme jak zablokovat a odblokovat jednotlivá tlačítka nástrojové lišty. Také se naučíme jak do nástrojové lišty vložit separátor.

import wx

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

        self.count = 5

        self.toolbar = self.CreateToolBar()
        self.toolbar.AddLabelTool(wx.ID_UNDO, '', wx.Bitmap('../icons/undo.png'))
        self.toolbar.AddLabelTool(wx.ID_REDO, '', wx.Bitmap('../icons/redo.png'))
        self.toolbar.EnableTool(wx.ID_REDO, False)
        self.toolbar.AddSeparator()
        self.toolbar.AddLabelTool(wx.ID_EXIT, '', wx.Bitmap('../icons/exit.png'))
        self.toolbar.Realize()

        self.Bind(wx.EVT_TOOL, self.OnExit, id=wx.ID_EXIT)
        self.Bind(wx.EVT_TOOL, self.OnUndo, id=wx.ID_UNDO)
        self.Bind(wx.EVT_TOOL, self.OnRedo, id=wx.ID_REDO)

        self.Centre()
        self.Show(True)

    def OnUndo(self, event):
        if self.count > 1 and self.count <= 5:
            self.count = self.count - 1

        if self.count == 1:
            self.toolbar.EnableTool(wx.ID_UNDO, False)

        if self.count == 4:
            self.toolbar.EnableTool(wx.ID_REDO, True)

    def OnRedo(self, event):
        if self.count < 5 and self.count >= 1:
            self.count = self.count + 1

        if self.count == 5:
            self.toolbar.EnableTool(wx.ID_REDO, False)

        if self.count == 2:
            self.toolbar.EnableTool(wx.ID_UNDO, True)

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

app = wx.App()
EnableDisable(None, -1, 'enable disable')
app.MainLoop()

V našem příkladu obsahuje lišta tři tlačítka. Jedno pro ukončení aplikace, zbylá dvě tlačítka se snaží simulovat funkci Zpět a Vpřed.

self.toolbar.EnableTool(wx.ID_REDO, False)
self.toolbar.AddSeparator()

Na začátku předchozího kódu je tlačítko Zpět zablokováno (disabled). Udělali jsme to zavoláním metody EnableTool(). Na druhém řádku vytváříme separátor. Ten má podobnou funkci jako v menu - odděluje skupiny tlačítka. Separátor se vytváří pomocí metody AddSeparator().

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

Článek stažen z webu Programujte.com [ http://programujte.com/clanek/2008072301-wxpython-menu-a-nastrojova-lista/ ].