在很多GUI程序中,常常在应用启动开始的时候,需要一个用户登录对话框,在那里用户必须输入用户名和密码, 如果密码和用户名正确,那么程序就继续加载,显示程序的主界面。
下面我们将实现一个登录窗口,它具有以下功能:
- 输入用户名及密码。
- 登录,如果用户名和密码成功匹配,则显示登录成功信息, 如果登录失败,则清除输入的信息,提示重新输入。
- 一共有三次输入机会,如果三次都出错,则直接退出应用。
在本文中我们将演示如何使用绝对布局方式和wxPython中的布局调节器Sizer来实现登录窗口的布局。
一、使用绝对位置实现布局
所谓绝对布局,就是在面板Panel上指定每个控件的绝对像素位置,指定该位置后,控件不会随窗口的大小变化而调整其位置。
import wx
class DialogLogin(wx.Dialog):
def __init__(self, *args, **kw):
super(DialogLogin, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.SetTitle("实战wxPython: 登录对话框演示")
self.SetSize(400, 280)
self.Bind(wx.EVT_CLOSE, self.OnClose)
panel = wx.Panel(self)
wx.StaticText(panel, wx.ID_ANY, "用户登录", pos = (160, 40))
wx.StaticText(panel, wx.ID_ANY, "用户名:", pos = (80, 80), size=(40, 24))
self.txtUsername = wx.TextCtrl(panel, wx.ID_ANY, pos = (140, 80), size=(160, 24))
wx.StaticText(panel, wx.ID_ANY, "密码:" , pos = (80, 120), size=(40, 24))
self.txtPassword = wx.TextCtrl(panel, wx.ID_ANY, pos = (140, 120), size=(160, 24), style = wx.TE_PASSWORD)
btnLogin = wx.Button(panel, wx.ID_ANY, "登录", pos = (100, 180), size = (80, 24))
btnLogin.Bind(wx.EVT_BUTTON, self.OnLogin)
btnCancel = wx.Button(panel, wx.ID_ANY, "取消", pos = (200, 180), size = (80, 24))
btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
self.inputCount = 0
self.Centre()
def OnClose(self, e):
print("Destroy dialog\n")
self.Destroy()
def OnLogin(self, e):
if self.txtUsername.GetValue() != "Admin":
wx.MessageBox("用户名错误", "提示信息", wx.OK|wx.ICON_INFORMATION)
self.CheckInput()
elif self.txtPassword.GetValue() != "Admin":
wx.MessageBox("密码错误", "提示信息", wx.OK|wx.ICON_INFORMATION)
self.CheckInput()
else:
wx.MessageBox("登录成功", "提示信息", wx.OK|wx.ICON_INFORMATION)
#退出应用
self.Destroy();
def OnCancel(self, e):
self.inputCount = 0;
self.txtUsername.Clear()
self.txtPassword.Clear()
self.txtUsername.SetFocus()
def CheckInput(self):
self.inputCount += 1
if self.inputCount == 3:
wx.MessageBox("三次错误输入,应用退出", "提示信息", wx.OK|wx.ICON_INFORMATION)
#退出应用
self.Destroy()
elif self.inputCount == 2:
wx.MessageBox("输入错误,还有一次机会", "提示信息", wx.OK|wx.ICON_INFORMATION)
elif self.inputCount == 1:
wx.MessageBox("输入错误,还有二次机会", "提示信息", wx.OK|wx.ICON_INFORMATION)
def main():
app = wx.App()
sample = DialogLogin(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
上面的代码演示了如何使用绝对布局方式来实现一个登录窗口,从代码中可以看到,我们创建的每一个子控件,都指定相对于父窗口 panel的绝对像素位置。
在代码中,我们绑定了窗口的关闭事件
self.Bind(wx.EVT_CLOSE, self.OnClose)
当我们点击窗口上的” X”按钮时,将触发这个事件,执行OnClose中的代码
def OnClose(self, e):
print("Destroy dialog\n")
self.Destroy()
关闭对话框。
图1:采用绝对布局实现的登录窗口
当输入的用户名为"Admin"和密码都为"Admin",显示登录成功对话框,点击确定后,将退出应用。
二、使用Sizer实现布局
使用各种Sizer调节器来实现布局的一个重要优点就是,当窗口的大小发生变化时,窗口内的控件会根据父窗口的变化来调整自身相对于父窗口的位置,这样,最终窗口的显示效果相对于绝对布局来说,会更协调和美观。
import wx
class DialogLogin(wx.Dialog):
def __init__(self, *args, **kw):
super(DialogLogin, self).__init__(*args, **kw)
self.InitUi()
def InitUi(self):
self.SetTitle("实战wxPython: 登录对话框演示")
self.SetSize(400, 280)
self.Bind(wx.EVT_CLOSE, self.OnClose)
panel = wx.Panel(self)
mainSizer = wx.BoxSizer(wx.VERTICAL)
# 顶部的提示信息
txtLogin = wx.StaticText(panel, wx.ID_ANY, "用户登录")
mainSizer.Add(txtLogin, 0, wx.ALL|wx.CENTER, 20)
# 用户名和密码
titleUsername = wx.StaticText(panel, wx.ID_ANY, "用户名:")
titlePassword = wx.StaticText(panel, wx.ID_ANY, "密码:")
self.textUsername = wx.TextCtrl(panel, wx.ID_ANY, size=(160,24));
self.textPassword = wx.TextCtrl(panel, wx.ID_ANY, size=(160,24), style = wx.TE_PASSWORD)
fgs = wx.FlexGridSizer(2, 2, 20, 20)
fgs.AddMany([(titleUsername), (self.textUsername, 1, wx.EXPAND),
(titlePassword), (self.textPassword, 1, wx.EXPAND)])
fgs.AddGrowableRow(1,1)
fgs.AddGrowableCol(1, 1)
mainSizer.Add(fgs, proportion=0, flag=wx.CENTER, border=40)
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnLogin = wx.Button(panel, wx.ID_ANY, "登录", size = (80, 24))
btnLogin.Bind(wx.EVT_BUTTON, self.OnLogin)
btnCancel = wx.Button(panel, wx.ID_ANY, "取消", size = (80, 24))
btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
btnSizer.Add(btnLogin)
btnSizer.Add(btnCancel, flag=wx.LEFT, border=40)
mainSizer.Add((-1, 40))
mainSizer.Add(btnSizer, 1, wx.CENTER, border = 20)
panel.SetSizer(mainSizer)
self.inputCount = 0
self.Centre()
def OnClose(self, e):
print("Destroy dialog\n")
self.Destroy()
def OnLogin(self, e):
if self.textUsername.GetValue() != "Admin":
wx.MessageBox("用户名错误", "提示信息", wx.OK|wx.ICON_INFORMATION)
self.CheckInput()
elif self.textPassword.GetValue() != "Admin":
wx.MessageBox("密码错误", "提示信息", wx.OK|wx.ICON_INFORMATION)
self.CheckInput()
else:
wx.MessageBox("登录成功", "提示信息", wx.OK|wx.ICON_INFORMATION)
#退出应用
self.Destroy();
def OnCancel(self, e):
self.inputCount = 0;
self.textUsername.Clear()
self.textPassword.Clear()
self.textUsername.SetFocus()
def CheckInput(self):
self.inputCount += 1
if self.inputCount == 3:
wx.MessageBox("三次错误输入,应用退出", "提示信息", wx.OK|wx.ICON_INFORMATION)
#退出应用
self.Destroy()
elif self.inputCount == 2:
wx.MessageBox("输入错误,还有一次机会", "提示信息", wx.OK|wx.ICON_INFORMATION)
elif self.inputCount == 1:
wx.MessageBox("输入错误,还有二次机会", "提示信息", wx.OK|wx.ICON_INFORMATION)
def main():
app = wx.App()
sample = DialogLogin(None)
sample.Show()
app.MainLoop()
if __name__ == "__main__":
main()
在上面的代码中,我们使用Sizer调节器来实现登录窗口的布局:
mainSizer = wx.BoxSizer(wx.VERTICAL)
首先我们创建一个垂直布局的调节器mainSizer作为我们的主调节器
txtLogin = wx.StaticText(panel, wx.ID_ANY, "用户登录")
mainSizer.Add(txtLogin, 0, wx.ALL|wx.CENTER, 20)
然后我们添加”用户登录”的静态文本提示信息,将其添加到 mainSizer中,并水平居中。
titleUsername = wx.StaticText(panel, wx.ID_ANY, "用户名:")
titlePassword = wx.StaticText(panel, wx.ID_ANY, "密码:")
self.textUsername = wx.TextCtrl(panel, wx.ID_ANY, size=(160,24));
self.textPassword = wx.TextCtrl(panel, wx.ID_ANY, size=(160,24), style = wx.TE_PASSWORD)
fgs = wx.FlexGridSizer(2, 2, 20, 20)
fgs.AddMany([(titleUsername), (self.textUsername, 1, wx.EXPAND),
(titlePassword), (self.textPassword, 1, wx.EXPAND)])
fgs.AddGrowableRow(1,1)
fgs.AddGrowableCol(1, 1)
mainSizer.Add(fgs, proportion=0, flag=wx.CENTER, border=40)
然后,我们生成用户名和密码输入解码,使用一个wx.FlexGridSizer调节器来完成对它们的布局。并将其添加到mainSizer中。
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
btnLogin = wx.Button(panel, wx.ID_ANY, "登录", size = (80, 24))
btnLogin.Bind(wx.EVT_BUTTON, self.OnLogin)
btnCancel = wx.Button(panel, wx.ID_ANY, "取消", size = (80, 24))
btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
btnSizer.Add(btnLogin)
btnSizer.Add(btnCancel, flag=wx.LEFT, border=40)
创建一个水平布局btnSizer, 将“登录”和“取消”按钮放入其中。
mainSizer.Add((-1, 40))
在主调节器中添加垂直方向40像素的间隔。
mainSizer.Add(btnSizer, 1, wx.CENTER, border = 20)
将btnSizer添加到主调节器mainSizer,完成整个布局。
图2:采用Sizer调节器实现的登录窗口
当输入的用户名为"Admin"和密码都为"Admin",显示登录成功对话框,点击确定后,将退出应用。
三、本文知识点
- 熟悉绝对布局和相对布局。
- 运用wxPyhton中的控件实现一个布局。
- 熟悉wx.Dialog的使用方法。
- 熟悉各种Sizer调节器的使用方法。
- 熟悉wx.MessageBox的使用方法。
前一篇:实战wxPython:048 - Book控件(第二部分)