wxPython, делая окно модальным - PullRequest
0 голосов
/ 24 мая 2019

Следующий код заставляет окно вести себя как wx.Dialog, но оно прекрасно работает только в Windows.В macOS кнопки в главном окне не отключены, а в Linux главное окно может быть развернуто и свернуто.

Как я могу иметь в MacOS и Linux такое же модальное поведение, как и в Windows?Я знаю, что мог бы отключить кнопки вручную, и я предполагаю, что должен быть способ обработки кнопок минимизации и максимизации, но perhpas есть более простой способ.

import wx

class MyFrame(wx.Frame):
    def __init__(self):
        title='Multiple consecutive windows (ShowModal)'
        super().__init__(None, title=title)

        self.WinNum = 5
        #### Widgets
        self.panel = wx.Panel(self)
        self.buttonShow = wx.Button(self.panel, pos=(50, 50), label='ShowModal')
        self.buttonTest = wx.Button(self.panel, pos=(50, 100), label='Test')
        #### Bind
        self.buttonShow.Bind(wx.EVT_BUTTON, self.ShowWindows)
        #### Position of the window
        self.SetPosition(pt=(50, 50))

    def ShowWindows(self, event):
        i = 0
        while i < self.WinNum:
            a = WinModal(i)
            a.ShowModal()
            i += 1

class WinModal(wx.Frame):
    def __init__(self, ThisWinNum):
        title = 'This is window number: ' + str(ThisWinNum)
        super().__init__(None, title=title)
        #### Variables
        self.ThisWinNum = ThisWinNum
        #### Widgets
        self.panel = wx.Panel(self)
        self.buttonOk = wx.Button(self.panel, pos=(50, 50), label='Ok')
        #### Positions
        self.SetPosition(pt=(200, 200))
        #### Bind
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_BUTTON, self.onOk)

    def ShowModal(self):
        """
        This function is the one giving the wx.FileDialog behavior
        """
        self._disabler = wx.WindowDisabler(self)
        self.Show()
        self.eventLoop = wx.GUIEventLoop()
        self.eventLoop.Run()

    def OnClose(self, event):
        """
        To handle closing the windows because you need to exit the eventLoop
        of the modal window.
        """
        del self._disabler
        self.eventLoop.Exit()
        self.Destroy()

    def onOk(self, event):
        print(self.ThisWinNum)
        self.cancel = False
        self.OnClose(event)

if __name__ == '__main__':
    app = wx.App()
    frame = MyFrame()
    frame.Show()
    app.MainLoop()
else:
    pass

1 Ответ

0 голосов
/ 28 июня 2019

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

Это можно сделать, выведя пользовательский класс из wx.Dialog вместо wx.Frame.Класс wx.Dialog дает пустое пространство, которое вы можете заполнить виджетами, как обычный wx.Frame, а также содержит метод ShoModal().Следовательно, вы можете показать свое окно как модальное окно.

import wx

class MainWin(wx.Frame):
    def __init__(self):
        super().__init__(None, title='My modal window')
        ####---- Variables
        self.frameFvar = None
        ####---- Widgets
        self.panel = wx.Panel(self)
        self.buttonF = wx.Button(self.panel, label='Show Normal')
        self.buttonM = wx.Button(self.panel, label='Show Modal')
        ####---- Sizer
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(self.buttonF, border=20, flag=wx.ALIGN_CENTER|wx.ALL)
        self.sizer.Add(self.buttonM, border=20, flag=wx.ALIGN_CENTER|wx.ALL)
        self.sizerM = wx.BoxSizer(wx.HORIZONTAL)
        self.sizerM.Add(self.sizer, border=20, 
            flag=wx.EXPAND|wx.ALIGN_CENTER|wx.ALL)
        self.panel.SetSizer(self.sizerM)
        self.sizerM.Fit(self)
        ####---- Position
        self.SetPosition(pt=(50, 50))
        ####---- Bind
        self.buttonF.Bind(wx.EVT_BUTTON, self.ShowAsNormal)
        self.buttonM.Bind(wx.EVT_BUTTON, self.ShowAsModal)
    #---

    def ShowAsNormal(self, event):
        if self.frameFvar == None:
            self.frameF = AsFrame(self)
            self.frameF.Show()
            self.frameFvar = True
        else:
            self.frameF.Raise()
    #---

    def ShowAsModal(self, event):
        self.frameM = AsDialog(self)
        if self.frameM.ShowModal() == wx.ID_OK:
            print("Exited by Ok button")
        else:
            print("Exited by X button")
        self.frameM.Destroy()
    #---
#---


class AsFrame(wx.Frame):
    def __init__(self, parent):
        super().__init__(parent=parent, title='Shown as a wx.Frame')
        ####---- Variables
        self.parent = parent
        ####---- Widgets
        self.a = MyPanel(self)
        ####---- Position
        self.SetPosition(pt=(50, 200))
        ####---- Bind
        self.Bind(wx.EVT_CLOSE, self.OnClose)
    #---

    def OnClose(self, event):
        self.parent.frameFvar = None
        self.Destroy()
    #---
#---


class AsDialog(wx.Dialog):
    def __init__(self, parent):
        super().__init__(parent=parent, title='Shown as a wx.Dialog')
        ####---- Variables
        self.SetEscapeId(12345)
        ####---- Widgets
        self.a = MyPanel(self)
        self.buttonOk = wx.Button(self, wx.ID_OK)
        ####---- Sizers
        self.sizerB = wx.StdDialogButtonSizer()
        self.sizerB.AddButton(self.buttonOk)
        self.sizerB.Realize()

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.a, border=10, flag=wx.EXPAND|wx.ALIGN_LEFT|wx.ALL)
        self.sizer.Add(self.sizerB, border=10, 
            flag=wx.EXPAND|wx.ALIGN_RIGHT|wx.ALL)

        self.SetSizer(self.sizer)

        ####---- Position
        self.SetPosition(pt=(550, 200))
    #---       
#---


class MyPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent=parent)
        ####---- Variables
        self.parent = parent
        ####---- Widgets
        label = ("The same window shown as a wx.Frame or a wx.Dialog")
        self.text = wx.StaticText(self, label=label, pos=(10, 10))
    #---
#---


if __name__ == '__main__':
    app = wx.App()
    frameM = MainWin()
    frameM.Show()
    app.MainLoop()
...