Я давно пользуюсь wxPython и вижу, что некоторые вопросы возникают довольно часто. Один из самых популярных — как запросить у пользователя свои учетные данные перед загрузкой остальной части приложения. Есть несколько подходов к этому, но я собираюсь сосредоточиться на простом решении, так как считаю, что это решение может быть использовано в качестве основы для более сложных решений.
По сути, мы хотим, чтобы пользователь увидел диалоговое окно входа в систему, где он должен ввести свое имя пользователя и пароль. Если они введут его правильно, программа продолжит загрузку и увидит основной интерфейс. Вы часто видите это на веб-сайтах, где часто используются клиенты веб-почты. Настольные приложения не включают эту функцию так часто, хотя вы увидите ее для приложения Stamps.com и для правоохранительных программ.
Давайте посмотрим на некоторый код:
import wx if "2.8" in wx.version(): import wx.lib.pubsub.setupkwargs from wx.lib.pubsub import pub else: from wx.lib.pubsub import pub ######################################################################## class LoginDialog(wx.Dialog): """ Class to define login dialog """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Dialog.__init__(self, None, title="Login") # user info user_sizer = wx.BoxSizer(wx.HORIZONTAL) user_lbl = wx.StaticText(self, label="Username:") user_sizer.Add(user_lbl, 0, wx.ALL|wx.CENTER, 5) self.user = wx.TextCtrl(self) user_sizer.Add(self.user, 0, wx.ALL, 5) # pass info p_sizer = wx.BoxSizer(wx.HORIZONTAL) p_lbl = wx.StaticText(self, label="Password:") p_sizer.Add(p_lbl, 0, wx.ALL|wx.CENTER, 5) self.password = wx.TextCtrl(self, style=wx.TE_PASSWORD|wx.TE_PROCESS_ENTER) p_sizer.Add(self.password, 0, wx.ALL, 5) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(user_sizer, 0, wx.ALL, 5) main_sizer.Add(p_sizer, 0, wx.ALL, 5) btn = wx.Button(self, label="Login") btn.Bind(wx.EVT_BUTTON, self.onLogin) main_sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(main_sizer) #---------------------------------------------------------------------- def onLogin(self, event): """ Check credentials and login """ stupid_password = "pa$w0rd!" user_password = self.password.GetValue() if user_password == stupid_password: print "You are now logged in!" pub.sendMessage("frameListener", message="show") self.Destroy() else: print "Username or password is incorrect!" ######################################################################## class MyPanel(wx.Panel): """""" #---------------------------------------------------------------------- def __init__(self, parent): """Constructor""" wx.Panel.__init__(self, parent) ######################################################################## class MainFrame(wx.Frame): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="Main App") panel = MyPanel(self) pub.subscribe(self.myListener, "frameListener") # Ask user to login dlg = LoginDialog() dlg.ShowModal() #---------------------------------------------------------------------- def myListener(self, message, arg2=None): """ Show the frame """ self.Show() if __name__ == "__main__": app = wx.App(False) frame = MainFrame() app.MainLoop()
Большая часть этого кода занята подклассом wx.Dialog, который мы называем LoginDialog . Вы заметите, что мы установили виджет управления текстом пароля для использования wx.TE_PASSWORDстиль, который будет скрывать символы, которые пользователь вводит в этот элемент управления. Обработчик событий — это то, где происходит настоящее действие. Здесь мы определяем глупый пароль, который мы используем для сравнения с тем, который вводит пользователь. В реальном мире вы, вероятно, возьмете хеш введенного пароля и сравните его с тем, который хранится в базе данных. Или вы можете отправить учетные данные на ваш сервер аутентификации и попросить вас сообщить, являются ли учетные данные пользователя законными или нет. В демонстрационных целях мы выбираем простой подход и просто проверяем пароль. Вы заметите, что мы полностью игнорируем то, что пользователь вводит для имени пользователя. Это нереально, но опять же, это всего лишь пример.
В любом случае, если пользователь вводит правильный пароль, обработчик событий отправляет сообщение через pubsub нашему объекту MainFrame, сообщая ему о завершении загрузки, а затем диалоговое окно уничтожается. Есть и другие способы сообщить основному фрейму о продолжении, например, используя флаг в классе диалога, с которым мы можем проверить. Вот реализация, которая демонстрирует этот последний метод:
import wx ######################################################################## class LoginDialog(wx.Dialog): """ Class to define login dialog """ #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Dialog.__init__(self, None, title="Login") self.logged_in = False # user info user_sizer = wx.BoxSizer(wx.HORIZONTAL) user_lbl = wx.StaticText(self, label="Username:") user_sizer.Add(user_lbl, 0, wx.ALL|wx.CENTER, 5) self.user = wx.TextCtrl(self) user_sizer.Add(self.user, 0, wx.ALL, 5) # pass info p_sizer = wx.BoxSizer(wx.HORIZONTAL) p_lbl = wx.StaticText(self, label="Password:") p_sizer.Add(p_lbl, 0, wx.ALL|wx.CENTER, 5) self.password = wx.TextCtrl(self, style=wx.TE_PASSWORD|wx.TE_PROCESS_ENTER) self.password.Bind(wx.EVT_TEXT_ENTER, self.onLogin) p_sizer.Add(self.password, 0, wx.ALL, 5) main_sizer = wx.BoxSizer(wx.VERTICAL) main_sizer.Add(user_sizer, 0, wx.ALL, 5) main_sizer.Add(p_sizer, 0, wx.ALL, 5) btn = wx.Button(self, label="Login") btn.Bind(wx.EVT_BUTTON, self.onLogin) main_sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(main_sizer) #---------------------------------------------------------------------- def onLogin(self, event): """ Check credentials and login """ stupid_password = "pa$w0rd!" user_password = self.password.GetValue() if user_password == stupid_password: print "You are now logged in!" self.logged_in = True self.Close() else: print "Username or password is incorrect!" ######################################################################## class MyPanel(wx.Panel): """""" #---------------------------------------------------------------------- def __init__(self, parent): """Constructor""" wx.Panel.__init__(self, parent) ######################################################################## class MainFrame(wx.Frame): """""" #---------------------------------------------------------------------- def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="Main App") panel = MyPanel(self) # Ask user to login dlg = LoginDialog() dlg.ShowModal() authenticated = dlg.logged_in if not authenticated: self.Close() self.Show() if __name__ == "__main__": app = wx.App(False) frame = MainFrame() app.MainLoop()
В этом примере мы добавили флаг в подкласс диалога, который мы назвали self.logged_in . Если пользователь вводит правильный пароль, мы сообщаем, чтобы диалог закрылся. Это заставляет wxPython возвращать управление обратно классу MainFrame, где мы проверяем эту переменную, чтобы увидеть, вошел ли пользователь в систему или нет. Если это не так, мы закрываем приложение. В противном случае мы загружаем приложение.
Завершение
Мы можем добавить несколько улучшений, таких как установка фокуса на первый текстовый элемент управления или добавление кнопки отмены. Я уверен, что вы можете думать о нескольких других самостоятельно. В целом, это должно помочь вам начать.