wxpython SetFocus и поле со списком EVT_KILL_FOCUS

Я пытаюсь понять, как работают EVT_KILL_FOCUS и SetFocus в поле со списком. Вот следующий код:

import wx

class MainWindow(wx.Frame):

    count = 1

    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(150,150), style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX)
        panel = wx.Panel(self, -1)

        self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
        self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)

        btn = wx.Button(panel, label="Test")

        MainFrameSizer = wx.BoxSizer(wx.VERTICAL)
        MainFrameSizer.Add(self.Calc_Display, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)
        MainFrameSizer.Add(btn, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 5)

        panel.SetSizer(MainFrameSizer)
        panel.Fit()
        self.Show()


    def OnKillFocus(self, event):
        print ('EVT_KILL_FOCUS was called %i times' %MainWindow.count)
        MainWindow.count += 1
        # self.Calc_Display.SetFocus()
        event.Skip()


app = wx.App(False)
frame = MainWindow(None, "Test")
app.MainLoop()

Если запустить это, вы будете получать печать каждый раз, когда поле со списком теряет фокус, что и ожидается. Если вы раскомментируете строку 28, тогда это станет странным. EVT_KILL_FOCUS вызывается снова и снова. Это поведение я пытаюсь понять. В программе, которую я пишу, я хочу, чтобы поле со списком сохраняло фокус, если условие не выполняется. Есть ли способы обойти это поведение?

Я нашел эту ссылку по вопросу, но не совсем понял: http://wiki.wxpython.org/Surviving%20with%20wxEVT%20KILL%20FOCUS%20under%20Microsoft%20Windows

Спасибо за любую помощь


person Vitor Rossi    schedule 20.08.2014    source источник


Ответы (1)


Прочитав ссылку, размещенную в вашем вопросе, и поиграв с вашим кодом, я пришел к выводу, что вызов SetFocus() на combobox, по-видимому, вызывает EVT_KILL_FOCUS в Windows. Я заметил, что при запуске программы она печатает оператор один раз, хотя этого не должно быть, поскольку combobox не теряет фокус.

Я попробовал две вещи:

Сначала нужно было переместить код поля со списком после кода кнопки. В этом случае, когда программа запускается, фокус находится на кнопке, и, конечно же, оператор не печатается!

Вот редактирование:

btn = wx.Button(panel, label="Test")

self.Calc_Display = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN|wx.TE_PROCESS_ENTER)
self.Calc_Display.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)

Второй был попытка привязать btn к обработчику, который устанавливает фокус на combobox

btn.Bind(wx.EVT_BUTTON, self.On_Button)

def On_Button(self, event):
    self.Calc_Display.SetFocus()

В этом случае оператор печатался дважды при каждом нажатии кнопки. Я предполагаю, что это один раз для потери фокуса и один раз для возврата фокуса. Обратите внимание, что в этом случае SetFocus() все еще закомментировано в OnKillFocus.

Вернемся к вашему коду: если SetFocus «раскомментирован», оператор печатается много раз, потому что он продолжает устанавливать фокус, который, в свою очередь, запускает событие, и оно продолжается в цикле. Это может быть неверным объяснением, но, тем не менее, это единственное, что мне пришло в голову.

person user2963623    schedule 21.08.2014
comment
По-видимому, SetFocus() запускает EVT_KILL_FOCUS под Windows. Кажется, нет способа обойти это, поэтому я решил вместо этого сделать что-то другое. Спасибо за помощь - person Vitor Rossi; 22.08.2014