Поле многострочного пароля wxPython

В wxPython стиль пароля работает только для однострочных текстовых элементов управления. Мне нужно поле многострочного пароля. Я думал о двух способах:

  1. Я создал шрифт с одним глифом (сплошная точка) в каждой точке кода. Тем не менее, я могу понять, что пользователи не хотят, чтобы на их машинах были установлены шрифты. В wxWidgets вы можете использовать приватные шрифты, но не в wxPython. Мне не хватает способа динамической загрузки этого шрифта для этого конкретного диалога.

  2. Создание подкласса wx.TextCtrl и реализация сохранения текста как введенного, но с отображением только одного символа. Это звучит намного сложнее. И нужны некоторые предложения о том, как я мог бы подойти к этому.

Мне НУЖНО это, Я ДУМАЛ над этим. Итак, я ищу некоторые мысли о двух способах, о которых я думал выше, или о любых других возможных реализациях.

2 ответа

Решение

Сохранение пароля в textctrl, как он введен!

import wx

########################################################################
class LoginDialog(wx.Dialog):
    """
    Class to define login dialog
    """
    def __init__(self):
        wx.Dialog.__init__(self, None, title="Login")
        self.logged_in = False
        self.attempts = 3
        self.stored_password = ""
        # 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)

        # password 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_MULTILINE)
        self.password.Bind(wx.EVT_TEXT,self.OnMask)
        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 OnMask(self, event):
        disp_pass = self.password.GetValue()
        #Test for backspace/clear event
        p_len = disp_pass.count('*')
        if p_len < len(self.stored_password):
            self.stored_password = self.stored_password[:p_len]
            return
        #Store the last input character
        try:
            char = disp_pass[-1]
            self.stored_password = self.stored_password + char
        #Mask the input
            self.password.ChangeValue("*" * len(disp_pass))
        except:
            pass

    def onLogin(self, event):
        valid_password = "password1\npassword2\npassword3"
        user_password = self.stored_password
        if user_password == valid_password:
            self.logged_in = True
            self.Close()
            return
        else:
            wx.MessageBox('Login failed', 'Error', wx.OK | wx.ICON_ERROR)
            self.stored_password = ""
            self.password.SetValue("")
        self.attempts -= 1
        if self.attempts < 1:
            wx.MessageBox('Too many Login attempts', 'Error', wx.OK | wx.ICON_ERROR)
            self.Close()

class MyPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        user_lbl = wx.StaticText(self, label="Log in Successfull")

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Main App")
        panel = MyPanel(self)
        dlg = LoginDialog()
        dlg.ShowModal()
        authenticated = dlg.logged_in
        dlg.Destroy()
        if not authenticated:
            wx.MessageBox('Login failed', 'Error', wx.OK | wx.ICON_ERROR)
            self.Destroy()
        self.Show()

if __name__ == "__main__":
    app = wx.App()
    frame = MainFrame()
    app.MainLoop()

Обратите внимание self.password.ChangeValue() скорее, чем self.password.SetValue(), предотвращает запуск EVT_TEXT при обновлении.

Вы можете использовать стили wx.TE_MULTILINE а также wx.TE_PASSWORD все вместе.

...
editor = wx.TextCtrl(..., style=wx.TE_MULTILINE | wx.TE_PASSWORD)
...
Другие вопросы по тегам