
Стильное и эффектное платье связано крючком, в технике Брюгского кружева. Особый шарм ему придает яркий алый цвет и кокетливый бант из атласной ленты.
Автор: Ангелина
Дата публикации: 2012-06-05T22:55:00.001+03:00

Стильное и эффектное платье связано крючком, в технике Брюгского кружева. Особый шарм ему придает яркий алый цвет и кокетливый бант из атласной ленты.
Автор: Ангелина
Дата публикации: 2012-06-05T22:55:00.001+03:00
В этой главе рассказывается о том, как:
9.1 Работа с модальными диалогами
9.1.1 Как создать модальный диалог
import wx
class SubclassDialog(wx.Dialog):
def __init__(self): #инициируем диалог
wx.Dialog.__init__(self, None, -1, 'Dialog Subclass',size=(300, 100))
okButton = wx.Button(self, wx.ID_OK, "OK", pos=(15, 15))
okButton.SetDefault()
cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel",pos=(115, 15))
if __name__ == '__main__':
app = wx.PySimpleApp()
dialog = SubclassDialog()
result = dialog.ShowModal() #показываем модальный диалог
if result == wx.ID_OK:
print "OK"
else:
print "Cancel"
dialog.Destroy()
после чего приложению остаётся лишь корректно обработать значения кнопок.
9.1.2 Как вывести пользователю сообщение?
Листинг 9.2
import wx
if __name__ == "__main__":
app = wx.PySimpleApp()
# с использованием классов
dlg = wx.MessageDialog(None, "Is this explanation OK?",
'A Message Box',wx.YES_NO | wx.ICON_QUESTION)
retCode = dlg.ShowModal()
if (retCode == wx.ID_YES):
print "yes"
else:
print "no"
dlg.Destroy()
# с использованием функции
retCode = wx.MessageBox("Is this way easier?", "Via Function",
wx.YES_NO | wx.ICON_QUESTION)
| Стиль | Описание |
|---|---|
| wx.CANCEL | Добавляет кнопку «отменить» с идентификатором wx.ID_CANCEL |
| wx.NO_DEFAULT | Если установлен флаг wx.YES_NO, то кнопкой по умолчанию будет «нет» |
| wx.OK | Добавляет кнопку «да» с идентификатором wx.ID_OK |
| wx.YES_DEFAULT | Если установлен флаг wx.YES_NO, то кнопкой по умолчанию будет «да». Такая настройка применяется по умолчанию |
| wx.YES_NO | Добавляет кнопки «да» и «нет» со значениями wx.ID_OK и wx.ID_NO соответственно |
Вторая группа флагов отвечает за знак, который будет отображён рядом с текстом:
| Стиль | Описание |
|---|---|
| wx.ICON_ERROR | Знак ошибки |
| wx.ICON_EXCLAMATION | Восклицательный знак |
| wx.ICON_HAND | То же, что и wx.ICON_ERROR |
| wx.ICON_INFORMATION | Знак информационного сообщения (буква i) |
| wx.ICON_QUESTION | Вопросительный знак |
Использование функции wx.MessageBox()
9.1.3 Как получить короткий текст от пользователя?
Листинг9.3
import wx
if __name__ == "__main__":
app = wx.PySimpleApp()
dialog = wx.TextEntryDialog(None,
"What kind of text would you like to enter?",
"Text Entry", "Default Value", style=wx.OK|wx.CANCEL)
if dialog.ShowModal() == wx.ID_OK:
print "You entered: %s" % dialog.GetValue()
dialog.Destroy()
9.2 Использование стандартных диалогов
9.2.1 Диалог выбора файла
Листинг 9.6
import wx
import os
if __name__ == "__main__":
app = wx.PySimpleApp()
wildcard = "Python source (*.py)|*.py|"
"Compiled Python (*.pyc)|*.pyc|"
"All files (*.*)|*.*"
dialog = wx.FileDialog(None, "Choose a file", os.getcwd(),
"", wildcard, wx.OPEN)
if dialog.ShowModal() == wx.ID_OK:
print dialog.GetPath()
dialog.Destroy()
Выбор файла
Выбор папки
Листинг 9.7
import wx
if __name__ == "__main__":
app = wx.PySimpleApp()
dialog = wx.DirDialog(None, "Choose a directory:",
style=wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
if dialog.ShowModal() == wx.ID_OK:
print dialog.GetPath()
dialog.Destroy()
9.2.2 Диалог выбора шрифта
9.3 Создание мастеров
import wx
import wx.wizard
# создаём простую страницу
class TitledPage(wx.wizard.WizardPageSimple):
def __init__(self, parent, title):
wx.wizard.WizardPageSimple.__init__(self, parent)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.sizer)
titleText = wx.StaticText(self, -1, title)
titleText.SetFont(
wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD))
self.sizer.Add(titleText, 0,
wx.ALIGN_CENTRE | wx.ALL, 5)
self.sizer.Add(wx.StaticLine(self, -1), 0,
wx.EXPAND | wx.ALL, 5)
if __name__ == "__main__":
app = wx.PySimpleApp()
# создаём экземпляр мастера
wizard = wx.wizard.Wizard(None, -1, "Simple Wizard")
# создаём страницы мастера
page1 = TitledPage(wizard, "Page 1")
page2 = TitledPage(wizard, "Page 2")
page3 = TitledPage(wizard, "Page 3")
page4 = TitledPage(wizard, "Page 4")
page1.sizer.Add(wx.StaticText(page1, -1,
"Testing the wizard"))
page4.sizer.Add(wx.StaticText(page4, -1,
"This is the last page."))
# задаём последовательность страниц
wx.wizard.WizardPageSimple_Chain(page1, page2)
wx.wizard.WizardPageSimple_Chain(page2, page3)
wx.wizard.WizardPageSimple_Chain(page3, page4)
# задаём размер мастера
wizard.FitToPage(page1)
# запускаем мастера
if wizard.RunWizard(page1):
print "Success"
Создание экземпляра wx.wizard.Wizard — первый шаг в использовании мастера. Конструктор класса выглядит так:
wx.wizard.Wizard(parent, id=-1, title=wx.EmptyString, bitmap=wx.NullBitmap, pos=wx.DefaultPosition)
В нашем примере parent, id, title и pos имеют тот же смысл, что и в конструкторе wx.Panel. Если передан аргумент bitmap, то он будет отображаться на каждой странице. Из доступных флагов стиля есть только wx.WIZARD_EX_HELPBUTTON, который отображает кнопку помощи. Это флаг расширенного стиля и его надо устанавливать используя двухступенчатый механизм, описанный в главе 8.
Обычно, для установки размера Вы будете использовать FitToSize(), как в нашем примере, но ничто не мешает Вам задать размер самому с помощью метода SetPageSize(), передав ему в качестве аргумента кортеж или экземпляр wx.Size. Для получения текущего размера используется метод GetPageSize(). В любом случае размер будет использоваться лишь для той части мастера, которая предназначена для отображения страниц, сам мастер будет большего размера (например, из-за кнопок «далее» и «назад» — прим. переводчика).
Контролировать работу мастера можно с помощью его же методов: метод GetCurrentPage() возвращает отображаемую страницу, если же мастер ещё не запущен он вернёт None. Определить, имеет ли текущая стра
ница следующую или предыдущую можно с помощью методов HasNextPage() и HasPrevPage(). Для запуска мастера используется метод RunWizard(), как видно из нашего листинга.
Мастер продуцирует командные события, которые Вы сами можете перехватывать и обрабатывать; они перечислены в таблице ниже. Каждое из этих событий относится к классу wx.wizard.WizardEvent, для которого доступно два метода. GetPage() вернёт нам страницу, на которой было создано событие, а GetDirection() вернёт True, если пользователь движется вперёд по мастеру, и False в другом случае.
| Событие | Описание |
|---|---|
| EVT_WIZARD_CANCEL | Создаётся, когда пользователь нажимает кнопку «отмена». Это событие может быть отменено с помощью метода Veto(). В таком случае диалог не завершит работу. |
| EVT_WIZARD_FINISHED | Создаётся, когда пользователь нажимает кнопку «готово» в конце мастера. |
| EVT_WIZARD_HELP | Создаётся, когда пользователь нажимает кнопку справки |
| EVT_WIZARD_PAGE_CHANGED | Создаётся после смены страницы для постобработки |
| EVT_WIZARD_PAGE_CHANGING | Создаётся когда пользователь нажал на кнопку изменения страницы, но страница ещё не изменилась. Это событие так же может быть отменено с помощью Veto(), например, если пользователь заполнил не все поля. |
9.4 Отображение подсказок при запуске
Листинг 9.12
import wx
if __name__ == "__main__":
app = wx.PySimpleApp()
provider = wx.CreateFileTipProvider("tips.txt", 0)
wx.ShowTip(None, provider, True)
Автор: Ishayahu Lastov
9.5 Использование валидаторов
9.5.1 Как с помощью валидатора убедиться, что я получил верные данные?
import wx
about_txt = """
Валидатор, используемый в этом примере проверяет наличие текста в
текстовых полях при нажатии на кнопку "ок" и не даёт Вам закрыть диалог,
если это условие не выполняется."""
# создаём подкласс валидатора
class NotEmptyValidator(wx.PyValidator):
def __init__(self):
wx.PyValidator.__init__(self)
def Clone(self):
"""
Обратите внимание, что каждый валидатор должен реализовать метод Clone().
"""
return NotEmptyValidator()
# метод проверки
def Validate(self, win):
textCtrl = self.GetWindow()
text = textCtrl.GetValue()
if len(text) == 0:
wx.MessageBox("This field must contain some text!", "Error")
textCtrl.SetBackgroundColour("pink")
textCtrl.SetFocus()
textCtrl.Refresh()
return False
else:
textCtrl.SetBackgroundColour(
wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
textCtrl.Refresh()
return True
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
class MyDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, -1, "Validators: validating")
# Создаём поля для ввода текста
about = wx.StaticText(self, -1, about_txt)
name_l = wx.StaticText(self, -1, "Name:")
email_l = wx.StaticText(self, -1, "Email:")
phone_l = wx.StaticText(self, -1, "Phone:")
# используем валидаторы
name_t = wx.TextCtrl(self, validator=NotEmptyValidator())
email_t = wx.TextCtrl(self, validator=NotEmptyValidator())
phone_t = wx.TextCtrl(self, validator=NotEmptyValidator())
# Используем стандартные ID кнопок
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
# размещаем виджеты с помощью координаторов
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
fgs = wx.FlexGridSizer(3, 2, 5, 5)
fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
fgs.Add(name_t, 0, wx.EXPAND)
fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
fgs.Add(email_t, 0, wx.EXPAND)
fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
fgs.Add(phone_t, 0, wx.EXPAND)
fgs.AddGrowableCol(1)
sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
self.SetSizer(sizer)
sizer.Fit(self)
app = wx.PySimpleApp()
dlg = MyDialog()
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()
9.5.2 Передача данных с помощью валидаторов
import wx
import pprint
about_txt = """
В данном примере валидатор используется для демонстрации
возможности автоматической передачи данных в и из текстового поля
при открытии и закрытии диалога."""
# объявляем валидатор
class DataXferValidator(wx.PyValidator):
def __init__(self, data, key):
wx.PyValidator.__init__(self)
self.data = data
self.key = key
def Clone(self):
"""
Будьте внимательны: каждый валидатор должен реализовать метод Clone()
"""
return DataXferValidator(self.data, self.key)
# не проверяем данные
def Validate(self, win):
return True
# вызывается при открытии диалога
def TransferToWindow(self):
textCtrl = self.GetWindow()
textCtrl.SetValue(self.data.get(self.key, ""))
return True
# вызывается при закрытии диалога
def TransferFromWindow(self):
textCtrl = self.GetWindow()
self.data[self.key] = textCtrl.GetValue()
return True
class MyDialog(wx.Dialog):
def __init__(self, data):
wx.Dialog.__init__(self, None, -1, "Validators: data transfer")
about = wx.StaticText(self, -1, about_txt)
name_l = wx.StaticText(self, -1, "Name:")
email_l = wx.StaticText(self, -1, "Email:")
phone_l = wx.StaticText(self, -1, "Phone:")
name_t = wx.TextCtrl(self,
validator=DataXferValidator(data, "name"))
email_t = wx.TextCtrl(self,
validator=DataXferValidator(data, "email"))
phone_t = wx.TextCtrl(self,
validator=DataXferValidator(data, "phone"))
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
fgs = wx.FlexGridSizer(3, 2, 5, 5)
fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
fgs.Add(name_t, 0, wx.EXPAND)
fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
fgs.Add(email_t, 0, wx.EXPAND)
fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
fgs.Add(phone_t, 0, wx.EXPAND)
fgs.AddGrowableCol(1)
sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
self.SetSizer(sizer)
sizer.Fit(self)
app = wx.PySimpleApp()
data = { "name" : "Jordyn Dunn" }
dlg = MyDialog(data)
dlg.ShowModal()
dlg.Destroy()
wx.MessageBox("You entered these values:nn" +
pprint.pformat(data))
app.MainLoop()
9.5.3 Как проверять данные в процессе ввода?
import wx
import string
about_txt = """
Валидатор, используемый в данном примере проверяет "на лету" ввод данных
пользователем и не ждёт нажатия кнопки "ок". Первое поле не допускает
ввода цифр, во второе поле можно ввести всё, что угодно, а в третье -
всё, кроме букв.
"""
class CharValidator(wx.PyValidator):
def __init__(self, flag):
wx.PyValidator.__init__(self)
self.flag = flag
# связываем функцию с событием ввода символа
self.Bind(wx.EVT_CHAR, self.OnChar)
def Clone(self):
"""
Будьте внимательны: каждый валидатор должен реализовать метод Clone()
"""
return CharValidator(self.flag)
def Validate(self, win):
return True
def TransferToWindow(self):
return True
def TransferFromWindow(self):
return True
# обработчик ввода данных в виджет
def OnChar(self, evt):
key = chr(evt.GetKeyCode())
if self.flag == "no-alpha" and key in string.letters:
return
if self.flag == "no-digit" and key in string.digits:
return
evt.Skip()
class MyDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, -1, "Validators: behavior
modification")
# Создаём поля для ввода текста
about = wx.StaticText(self, -1, about_txt)
name_l = wx.StaticText(self, -1, "Name:")
email_l = wx.StaticText(self, -1, "Email:")
phone_l = wx.StaticText(self, -1, "Phone:")
# добавляем валидатор
name_t = wx.TextCtrl(self, validator=CharValidator("no-digit"))
email_t = wx.TextCtrl(self, validator=CharValidator("any"))
phone_t = wx.TextCtrl(self, validator=CharValidator("no-alpha"))
okay = wx.Button(self, wx.ID_OK)
okay.SetDefault()
cancel = wx.Button(self, wx.ID_CANCEL)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(about, 0, wx.ALL, 5)
sizer.Add(wx.StaticLine(self), 0, wx.EXPAND|wx.ALL, 5)
fgs = wx.FlexGridSizer(3, 2, 5, 5)
fgs.Add(name_l, 0, wx.ALIGN_RIGHT)
fgs.Add(name_t, 0, wx.EXPAND)
fgs.Add(email_l, 0, wx.ALIGN_RIGHT)
fgs.Add(email_t, 0, wx.EXPAND)
fgs.Add(phone_l, 0, wx.ALIGN_RIGHT)
fgs.Add(phone_t, 0, wx.EXPAND)
fgs.AddGrowableCol(1)
sizer.Add(fgs, 0, wx.EXPAND|wx.ALL, 5)
btns = wx.StdDialogButtonSizer()
btns.AddButton(okay)
btns.AddButton(cancel)
btns.Realize()
sizer.Add(btns, 0, wx.EXPAND|wx.ALL, 5)
self.SetSizer(sizer)
sizer.Fit(self)
app = wx.PySimpleApp()
dlg = MyDialog()
dlg.ShowModal()
dlg.Destroy()
app.MainLoop()
В этой главе Вы узнаете:
10.1 Создаём меню
10.1.1 Как создать полосу меню и прикрепить её к фрейму.
10.1.2 Как создать меню и прикрепить его к полосе меню?
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Simple Menu Example")
p = wx.Panel(self)
# создаём панель меню
menuBar = wx.MenuBar()
# создаём меню
menu = wx.Menu()
# добавляем меню к панели меню
menuBar.Append(menu, "Left Menu")
menu2 = wx.Menu()
menuBar.Append(menu2, "Middle Menu")
menu3 = wx.Menu()
menuBar.Append(menu3, "Right Menu")
self.SetMenuBar(menuBar)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()| Функция | Описание |
|---|---|
| Append(menu, title) | Добавляет menu в конец полосы меню (то есть в после последнего правого элемента). Параметр title используется для отображения нового меню. При удачном выполнении возвращает True, иначе — False. |
Insert(pos, menu, title) | Вставляет переданное menu в заданную в pos позицию (после данного вызова выражение GetMenu(pos)==menu будет истинно). Как и при вставке в список, все позиции всех последующих меню сдвигаются вправо. Отсчёт позиций начинается с 0, так что pos=0 эквивалентно помещению меню в крайнюю левую позицию полосы меню. Если в качестве pos передать результат вызова GetMenuCount(), то результат будет такой же как при вызове метода Append(). Параметр title используется для отображения нового меню. При удачном выполнении возвращает True, иначе — False. |
Remove(pos) | Удаляет меню из позиции pos, сдвигая оставшиеся меню влево. Возвращает то меню, которое было удалено. |
Replace(pos, menu, title) | Заменяет меню на позиции pos меню переданным в аргументе menu а для отображения использует параметр title. Не затрагивает остальные меню в полосе. Возвращает то меню, которое раньше находилось на этом месте. |
| Метод | Описание |
|---|---|
| EnableTop(pos, enable) | Делает меню на позиции pos доступным или нет, в зависимости от значения параметра enable — True или False. |
| GetMenu(pos) | Возвращает объект меню, находящийся в заданной позиции. |
| GetMenuCount() | Возвращает количество меню в полосе меню. |
| FindMenu(title) | Возвращает числовой индекс меню в полосе меню при заданном title. Если такого меню нет, метод возвращает wx.NOT_FOUND. Метод игнорирует декораторы акселераторов (то есть значки перед буквой для быстрого вызова) при их наличии. |
| GetLabelTop(pos) SetLabelTop(pos, label) | Метод установки и получения метки меню в данной позиции |
10.1.3 Как добавить элементы в выпадающее меню?
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Menu Example with StatusBar")
p = wx.Panel(self)
self.CreateStatusBar()
menu = wx.Menu()
simple = menu.Append(-1, "Simple menu item",
"This is some help text")
menu.AppendSeparator()
exit = menu.Append(-1, "Exit",
"Selecting this item will exit the program")
self.Bind(wx.EVT_MENU, self.OnSimple, simple)
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self
.SetMenuBar(menuBar)
def OnSimple(self, event):
wx.MessageBox("You selected the simple menu item")
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
Все они ведут себя так, как и ожидается из их названия.
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Add Menu Items")
p = wx.Panel(self)
self.txt = wx.TextCtrl(p, -1, "new item")
btn = wx.Button(p, -1, "Add Menu Item")
# связываем метод с событием кнопки
self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.txt, 0, wx.ALL, 20)
sizer.
Add(btn, 0, wx.TOP|wx.RIGHT, 20)
p.SetSizer(sizer)
self.menu = menu = wx.Menu()
simple = menu.Append(-1, "Simple menu item")
menu.AppendSeparator()
exit = menu.Append(-1, "Exit")
self.Bind(wx.EVT_MENU, self.OnSimple, simple)
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self.SetMenuBar(menuBar)
def OnSimple(self, event):
wx.MessageBox("You selected the simple menu item")
def OnExit(self, event):
self.Close()
def OnAddItem(self, event):
# добавляем элемент меню
item = self.menu.Append(-1, self.txt.GetValue())
# связываем его с методом
self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item)
def OnNewItemSelected(self, event):
wx.MessageBox("You selected a new item")
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
10.1.4 Как отвечать на события меню?
| Тип события | Описание |
|---|---|
| EVT_MENU_CLOSE | Возникает когда меню закрывается |
| EVT_MENU_HIGHLIGHT | Возникает при подсветке (наведении на) элемента меню. Связано с конкретным id. По умолчанию отображает подсказку в статусной панели фрейма |
| EVT_MENU_HIGHLIGHT_ALL | Возникает когда меню подсвечивается на при этом не привязано к конкретному id, другими словами может быть только один обработчик этого события для всей полосы меню. Его следует использовать если Вы хотите чтобы происходило какое-то действие при подсвечивании любого элемента меню. |
| EVT_MENU_OPEN | Во зникает когда меню открывается |
После того, как мы обсудили основы создания меню, можно перейти к описанию того, как работать с элементами меню.
10.2 Работа с элементами меню
10.2.1 Как найти определённый элемент меню в меню?
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Find Item Example")
p = wx.Panel(self)
self.txt = wx.TextCtrl(p, -1, "new item")
btn = wx.Button(p, -1, "Add Menu Item")
self.Bind(wx.EVT_BUTTON, self.OnAddItem, btn)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.txt, 0, wx.ALL, 20)
sizer.Add(btn, 0, wx.TOP|wx.RIGHT, 20)
p.SetSizer(sizer)
self.menu = menu = wx.Menu()
simple = menu.Append(-1, "Simple menu item")
menu.AppendSeparator()
exit = menu.Append(-1, "Exit")
self.Bind(wx.EVT_MENU, self.OnSimple, simple)
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self.SetMenuBar(menuBar)
def OnSimple(self, event):
wx.MessageBox("You selected the simple menu item")
def OnExit(self, event):
self.Close()
def OnAddItem(self, event):
item = self.menu.Append(-1, self.txt.GetValue())
self.Bind(wx.EVT_MENU, self.OnNewItemSelected, item)
def OnNewItemSelected(self, event):
# получаем элемент меню
item = self.GetMenuBar().FindItemById(event.GetId())
text = item.GetText()
wx.MessageBox("You selected the '%s' item" % text)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
def FindMenuInMenuBar(menuBar, title):
pos = menuBar.FindMenu(title)
if pos == wx.NOT_FOUND:
return None
return menuBar.GetMenu(pos)
Таблица 10.4 Методы взаимодействия wx.MenuBar
| Метод | Описание |
|---|---|
| FindMenuItem(menuString, itemString) | Ищет элемент меню с названием itemString в меню с названием menuString. Либо возвращает найденный элемент меню либо wx.NOT_FOUND |
FindItemById(id | Возвращает элемент меню, ассоциированный с переданным идентификатором. Если такого элемента нет — возвращает None. |
GetHelpString(id) SetHelpString(id, helpString) | Методы для получения и установки строки помощи для элемента меню с переданным идентификатором. Если такого элемента меню нет, метод установки вернёт «», а метод установки просто ничего не сделает. |
GetLabel(id) SetLabel(id,label) | Методы получения и установки для отображаемого названия элемента меню с переданным идентификатором. Обрабатывает отсутствующие э лементы так же как и методы для строки помощи. Эти методы следует использовать только после того, как полоса меню была соединена с фреймом. |
Таблица 10.4 Методы взаимодействия wx.Menu
| Метод | Описание |
|---|---|
| FindItem(itemString) | Возвращает элемент меню с названием либо wx.NOT_FOUND |
| FindItemById(id) | Как и у полосы меню |
| FindItemByPosition(pos) | Возвращает элемент меню, находящийся в данной позиции |
| GetHelpString(id) SetHelpString(id, helpString) | Как и у полосы меню |
| GetLabel(id) SetLabel(id,label) | Как и у полосы меню |
10.2.2 Как я могу активировать или деактивировать элемент меню?
Листинг 10.5
import wx
ID_SIMPLE = wx.NewId()
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Enable/Disable Menu Example")
p = wx.Panel(self)
self.btn = wx.Button(p, -1, "Disable Item", (20,20))
self.Bind(wx.EVT_BUTTON, self.OnToggleItem, self.btn)
menu = wx.Menu()
menu.Append(ID_SIMPLE, "Simple menu item")
self.Bind(wx.EVT_MENU, self.OnSimple, id=ID_SIMPLE)
menu.AppendSeparator()
menu.Append(wx.ID_EXIT, "Exit")
self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self.SetMenuBar(menuBar)
def OnSimple(self, event):
wx.MessageBox("You selected the simple menu item")
def OnExit(self, event):
self.Close()
def OnToggleItem(self, event):
menubar = self.GetMenuBar()
enabled = menubar.IsEnabled(ID_SIMPLE)
menubar.Enable(ID_SIMPLE, not enabled)
self.btn.SetLabel(
(enabled and "Enable" or "Disable") + " Item")
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
10.2.3 Как прикрепить к элементу меню акселератор (горячую клавишу)
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Accelerator Example")
p = wx.Panel(self)
menu = wx.Menu()
# создаём мнемонику
simple = menu.Append(-1, "Simple &menu item")
# создаём акселератор
accel = menu.Append(-1, "&AcceleratedtCtrl-A")
menu.AppendSeparator()
exit = menu.Append(-1, "E&xit")
self.Bind(wx.EVT_MENU, self.OnSimple, simple)
self.Bind(wx.EVT_MENU, self.OnAccelerated, accel)
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "&Menu")
self.SetMenuBar(menuBar)
# используем таблицу акселераторов
acceltbl = wx.AcceleratorTable( [
(wx.ACCEL_CTRL, ord('Q'), exit.GetId())
])
self.SetAcceleratorTable(acceltbl)
def OnSimple(self, event):
wx.MessageBox("You selected the simple menu item")
def OnAccelerated(self, event):
wx.MessageBox("You selected the accelerated menu item")
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
Использование акселераторов
| Акселератор | Клавиша |
|---|---|
| del | Delete |
| delete | Delete |
| down | Down arrow |
| end | End |
| enter | Enter |
| esc | Escape |
| escape | Escape |
| home | Home |
| ins | Insert |
| insert | Insert |
| left | Left arrow |
| pgdn | Page down |
| pgup | Page up |
| return | Enter |
| right | Right arrow |
| space | Space bar |
| tab | Tab |
| up | Up arrow |
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Toggle Items Example")
p = wx.Panel(self)
menuBar = wx.MenuBar()
menu = wx.Menu()
exit = menu.Append(-1, "Exit")
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar.Append(menu, "Menu")
menu = wx.Menu()
menu.AppendCheckItem(-1,"Check Item 1")
menu.AppendCheckItem(-1,"Check Item 2")
menu.AppendCheckItem(-1,"Check Item 3")
menu.AppendSeparator()
menu.AppendRadioItem(-1,"Radio Item 1")
menu.AppendRadioItem(-1,"Radio Item 2")
menu.AppendRadioItem(-1, "Radio Item 3")
menuBar.Append(menu, "Toggle Items")
self.SetMenuBar(menuBar)
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Sub-menu Example")
p = wx.Panel(self)
menu = wx.Menu()
submenu = wx.Menu()
submenu.Append(-1, "Sub-item 1")
submenu.Append(-1, "Sub-item 2")
# добавляем подменю
menu.AppendMenu(-1, "Sub-menu", submenu)
menu.AppendSeparator()
exit = menu.Append(-1, "Exit")
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self.SetMenuBar(menuBar)
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
10.3.2 Как создавать всплывающие меню?
Рисунок 10.6
Листинг 10.9
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
"Popup Menu Example")
self.panel = p = wx.Panel(self)
menu = wx.Menu()
exit = menu.Append(-1, "Exit")
self.Bind(wx.EVT_MENU, self.OnExit, exit)
menuBar = wx.MenuBar()
menuBar.Append(menu, "Menu")
self.SetMenuBar(menuBar)
wx.StaticText(p, -1,
"Right-click on the panel to show a popup menu",
(25,25))
# создаём меню
self.popupmenu = wx.Menu()
# наполняем его
for text in "one two three four five".split():
item = self.popupmenu.Append(-1, text)
self.Bind(wx.EVT_MENU, self.OnPopupItemSelected, item)
# связываем всплывающее меню с событием для его вызова
p.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup)
# показываем всплывающее меню
def OnShowPopup(self, event):
pos = event.GetPosition()
pos = self.panel.ScreenToClient(pos)
sel f.panel.PopupMenu(self.popupmenu, pos)
def OnPopupItemSelected(self, event):
item = self.popupmenu.FindItemById(event.GetId())
text = item.GetText()
wx.MessageBox("You selected item '%s'" % text)
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyFrame()
frame.Show()
app.MainLoop()
import wx
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,
«Fancier Menu Example»)
p = wx.Panel(self)
menu = wx.Menu()
bmp = wx.Bitmap(«open.png», wx.BITMAP_TYPE_PNG)
item = wx.MenuItem(menu, -1, «Has Open Bitmap»)
# добавляем собственную картинку
item.SetBitmap(bmp)
menu.AppendItem(item)
if 'wxMSW' in wx.PlatformInfo:
font = wx.SystemSettings.GetFont(
wx.SYS_DEFAULT_GUI_FONT)
font.SetWeight(wx.BOLD)
item = wx.MenuItem(menu, -1, «Has Bold Font»)
# изменяем шрифт
item.SetFont(font)
menu.AppendItem(item)
item = wx.MenuItem(menu, -1, «Has Red Text»)
# изменяем цвет
item.SetTextColour(«red»)
menu.AppendItem(item)
menu.AppendSeparator()
exit = menu.Append(-1, «Exit»)
self.Bind(wx.EVT_MENU, self.OnExit, exit)
| Методы | Описание |
|---|---|
| GetBackgroundColour() SetBackgroundColour(colour) | Тип свойства — wx.Colour. Установщику так же можно передать строку с именем цвета wxPython. Управляет фоновым цветом элемента меню. |
| GetFont() SetFont(font) | Управляет шрифтом элемента. Тип — wx.Font |
| GetTextColour() SetTextColour(colour) | Управляет цветом шрифта элемента. Тип как и у методов для цвета фона |
10.4.2 Логичная группировка элементов
Твёрдо придерживайтесь стандартов при упорядочивании меню
| Комбинация клавиш | Функция |
|---|---|
| Crtl+a | Выделить всё |
| Crtl+c | Копировать |
| Crtl+f | Искать |
| Crtl+g | Искать далее |
| Crtl+n | Новое |
| Crtl+o | Открыть |
| Crtl+p | Печатать |
| Crtl+q | Выйти |
| Crtl+s | Сохранить |
| Crtl+v | Вставить |
| Crtl+w | Закрыть |
| Crtl+x | Вырезать |
| Crtl+z | Отменить |
Показывайте текущий статус переключателей