Подтвердить что ты не робот

WxPython: вызов события вручную

Как я могу вызвать конкретное событие вручную из своего собственного кода?

4b9b3361

Ответ 2

Старая тема, но я думаю, что это выяснилось после того, как ее смутило в течение долгого времени, поэтому, если кто-то еще придет сюда искать ответ, это может помочь.

Чтобы вручную разместить событие, вы можете использовать

self.GetEventHandler().ProcessEvent(event)

(wxWidgets docs здесь, wxPython docs здесь)

или

wx.PostEvent(self.GetEventHandler(), event)

(wxWidgets docs, документы wxPython)

где event - событие, которое вы хотите опубликовать. Построить событие, например,

wx.PyCommandEvent(wx.EVT_BUTTON.typeId, self.GetId())

если вы хотите опубликовать событие EVT_BUTTON. Сделать это PyCommandEvent означает, что он будет распространяться вверх; другие типы событий не распространяются по умолчанию.

Вы также можете создавать настраиваемые события, которые могут переносить любые данные, которые вы хотите. Вот пример:

myEVT_CUSTOM = wx.NewEventType()
EVT_CUSTOM = wx.PyEventBinder(myEVT_CUSTOM, 1)

class MyEvent(wx.PyCommandEvent):
    def __init__(self, evtType, id):
        wx.PyCommandEvent.__init__(self, evtType, id)
        myVal = None

    def SetMyVal(self, val):
        self.myVal = val

    def GetMyVal(self):
        return self.myVal

(Я думаю, что нашел этот код в архиве списка рассылки где-то, но я не могу найти его снова. Если это ваш пример, спасибо! Пожалуйста, добавьте комментарий и возьмите кредит на это!)

Итак, чтобы отправить пользовательское событие:

event = MyEvent(myEVT_CUSTOM, self.GetId())
event.SetMyVal('here is some custom data')
self.GetEventHandler().ProcessEvent(event)

и вы можете связать его так же, как и любое другое событие

self.Bind(EVT_CUSTOM, self.on_event)

и получить пользовательские данные в обработчике событий

def on_event(self, e):
    data = e.GetMyVal()
    print 'custom data is: {0}'.format(data)

Или добавьте пользовательские данные в конструктор событий и сохраните шаг:

class MyEvent(wx.PyCommandEvent):
    def __init__(self, evtType, id, val = None):
        wx.PyCommandEvent.__init__(self, evtType, id)
        self.myVal = val

и др.

Надеюсь, это кому-то поможет.

Ответ 3

Простой и понятный способ сделать это с помощью последних версий wxPython (см. http://wiki.wxpython.org/CustomEventClasses):

   # create event class
   import wx.lib.newevent
   SomeNewEvent, EVT_SOME_NEW_EVENT = wx.lib.newevent.NewEvent()

   # post it, with arbitrary data attached
   wx.PostEvent(target, SomeNewEvent(attr1=foo, attr2=bar))

   # bind it as usual
   target.Bind(EVT_SOME_NEW_EVENT, target.handler)

Ответ 4

Хотя такие методы, как PostEvent и ProcessEvent, упомянутые в других ответах, могут в PostEvent роде делать это, имейте в PostEvent, что они имеют существенные ограничения:

  • Вы ограничены в том, какие события вы можете легко создать. Например, нет никакого способа создать wx.KeyEvent с определенным кодом ключа, потому что конструктор не принимает код ключа и там нет установщика. Возможно, для этого есть обходные пути (например, KeyEvent подкласса KeyEvent), но вам, по сути, придется взломать ограничения инфраструктуры.
  • Даже для событий, которые вы можете создать, например, событие щелчка, поведение, которое вы получаете от программной отправки события, не будет соответствовать поведению, которое вы получите от фактического выполнения действия от имени пользователя, потому что нативная обработка события выиграла ' т огонь. Например, программный запуск события щелчка по текстовому полю не даст фокусу текстового поля.

Я бы рекомендовал не использовать PostEvent или ProcessEvent в большинстве случаев. Если вы просто хотите запустить функцию обработки событий, то создание событий вручную бессмысленно; вместо этого просто вызовите функцию явно. Если вы хотите их, потому что вы пытаетесь написать автоматизированный тест пользовательского интерфейса, то вы, вероятно, не собираетесь закончить тем, что удовлетворяет вас из-за ограничений, перечисленных выше; Вместо этого я бы рекомендовал написать что-то, что фактически имитирует щелчки и нажатия клавиш на уровне диспетчера ОС/рабочего стола, используя wx.UIActionSimulator. Это в некотором роде и будет контролировать вашу системную мышь и клавиатуру, что обычно делает такие тесты неподходящими для набора тестов, который вы запускаете на компьютере разработчика... но, по крайней мере, он работает, что больше, чем можно сказать для диспетчеризации события с PostEvent.

Ответ 5

Вы хотите, чтобы вы отправили сообщение?

:: wxPostEvent void wxPostEvent (wxEvtHandler * dest, wxEvent & событие)

В приложении GUI эта функция помещает событие в указанный dest использование объекта wxEvtHandler:: AddPendingEvent. В противном случае он отправляет событие немедленно используя wxEvtHandler:: ProcessEvent. См. соответствующая документация для подробностей (и оговорки).

Включить файлы

<wx/app.h>

wxPython API docs

Ответ 6

Я полагаю, это зависит от того, с чем связано ваше событие, но мне нужно было сделать то же самое с LabelFrame, который отображал данные, когда вы выбирали элемент в списке. Вот как я смог это сделать:

'This is the line that binds my function "get_selected_location()"
to the action of selecting an item in my List box.'

self.list1_scoring.bind('<<ListboxSelect>>', self.get_selected_location)

Поэтому всякий раз, когда вы щелкаете по элементу в моем поле "list1_scoring", запускается get_selected_location(), и сведения о выбранном элементе появляются в другом LabelFrame. Мне нужно было вызвать это событие после завершения процесса обновления, чтобы обновить окно отображения. Поэтому я добавил эту строку в конце функции, которая запускает обновление.

self.get_selected_location('<<ListboxSelect>>')

Это снова запускает get_selected_location(), как будто я только что снова нажал на свой список.