Диалог не является модальным, когда ProgressDialog и Dialog открываются последовательно - PullRequest
0 голосов
/ 02 октября 2018

Я использую wxPython 4.0.1 msw (phoenix) с Python 3.6.5 на компьютере с Windows7, а также wxPython 2.9.4 с Python 2.7.

Я наблюдаю проблему смодальный диалог, который не блокирует доступ к родительскому окну позади.Это происходит только в том случае, если я запускаю диалог прогресса, а затем модальный диалог.Это поведение как-то связано с пользовательскими диалогами.У встроенных диалогов, таких как wx.MessageDialog, похоже, нет этой проблемы.

Чтобы изолировать проблему, я написал пример.Первые две кнопки открывают либо прогресс, либо модальный диалог и работают правильно.Третья кнопка открывает оба диалога последовательно.В этом случае модальная функциональность пользовательского диалога не работает, и я могу получить доступ и закрыть мэйнфрейм.Это вызывает многочисленные проблемы.

Диалог не является модальным, к главному окну можно получить доступ и закрыть его

import wx    

class SomeDialog(wx.Dialog):

    def __init__(self, parent):
        wx.Dialog.__init__(self, parent, title='SomeDialog',
                           style=wx.DEFAULT_DIALOG_STYLE)
        self.button_ok = wx.Button(self, wx.ID_OK, size=(120,-1))
        hsizer = wx.BoxSizer(wx.HORIZONTAL)
        hsizer.Add(self.button_ok, 0, wx.ALL|wx.ALIGN_CENTER, 10)
        self.SetSizer(hsizer)
        self.SetSize(self.BestSize)
        self.Layout()

class TestFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, -1, size=(400, 400))
        self.button_progress = wx.Button(self, -1, 'Show Progress')
        self.button_modal = wx.Button(self, -1, 'Show Modal')
        self.button_both = wx.Button(self, -1, 'Show Both')
        self.Bind(wx.EVT_BUTTON, self.on_button, self.button_progress)
        self.Bind(wx.EVT_BUTTON, self.on_button, self.button_modal)
        self.Bind(wx.EVT_BUTTON, self.on_button, self.button_both)

        sizer = wx.BoxSizer()
        sizer.Add(self.button_progress)
        sizer.Add(self.button_modal)
        sizer.Add(self.button_both)
        self.SetSizer(sizer)

    def on_button(self, event):
        if event.EventObject is self.button_progress:
            self._show_progress_dialog()
        elif event.EventObject is self.button_modal:
            self._show_modal_dialog()
        else:
            self._show_progress_dialog()
            self._show_modal_dialog()

    def _show_progress_dialog(self):
        max = 10
        dlg = wx.ProgressDialog('Progress dialog example', 'Some message',
                                maximum=max, parent=self, 
                                style=wx.PD_APP_MODAL|wx.PD_AUTO_HIDE)
        keepGoing = True
        count = 0
        while keepGoing and count < max:
            count += 1
            wx.MilliSleep(250)
            wx.Yield()
            (keepGoing, skip) = dlg.Update(count)
        dlg.Destroy()

    def _show_modal_dialog(self):
        with SomeDialog(self) as dlg:
            dlg.CenterOnParent()
            dlg.ShowModal()

if __name__ == '__main__':
    app = wx.App()
    frame = TestFrame()
    frame.Show()
    app.MainLoop()

В случае, если это проблема в среде wxpython ине проблема с моей реализацией, было бы замечательно, если бы кто-то мог предоставить мне обходной путь для показа таких диалогов в последовательности.

Ответы [ 2 ]

0 голосов
/ 24 октября 2018

Тем временем я сам нашел обходной путь, которым я хотел бы поделиться.

Я добавил обработчик, перехватывающий событие закрытия окна.

class TestFrame(wx.Frame):
    def __init__(self):
        #...
        self.Bind(wx.EVT_CLOSE, self.on_close)

Эта функция события проверяет, является ли какой-либо дочерний диалог открытым и модальным, и выполняет вето.

def on_close(self, event):
    # In case any modal dialog is open, prevent the frame from closing.
    for children in (c for c in self.Children if isinstance(c, wx.Dialog)):
        if children.IsModal():
            event.Veto()
            return
    event.Skip()

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

0 голосов
/ 17 октября 2018

Это похоже на ошибку для меня.Я не уверен, почему это происходит, но один из обходных путей - использовать wx.CallLater

, изменив _show_modal_dialog на:

def _show_modal_dialog(self):
    def _make_dialog():
        with SomeDialog(self) as dlg:
            dlg.CenterOnParent()
            dlg.ShowModal()

    wx.CallLater(50, _make_dialog) # 50 mils is arbitrary

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...