拓展功能:
(一)密码隐藏及显示功能
进入wxfb,在设计好的登录窗口下,先在密码的输入框中随便输点什么,在属性栏中找到style,点击左侧加号,展开子菜单,勾选wxTE_PASSWPRD,可以看到输入框中刚才输入的内容变成了黑点点,把这个框的名字改为m_PassWord(记得把代码中登录那个方法的name也改过来)。
此时我们在这个输入框后,再添加一个输入框,命名为m_textCtrl15,然后把该框隐藏(在属性框中找到hidden并勾选)(记得对照一下两个框开的效果,比如第一个框开了顶格,另一个框也要开,否则后面显示会出问题,就是要让用户以为这里其实是一个框,其实是两个一摸一样的框在切换):
就可以发现又变成了一个输入框,然后在后面再添加一个wxCheckBox(组件中Common下),修改其label为显示密码:
为了使账号密码输入框对其,我们在账号的输入框之后添加一个占位符(Layout-spacer),在属性框中略微调整这个输入框的大小,使其对齐(其实是要下面的输入框比上面的稍微长一点点才能在程序中实现对齐,自己一点一点调):
给刚添加的这个显示按钮添加一个事件:evt_visiable,记得F8生成代码
在后端LoginFrame下实现这个方法:
# 这是一个隐藏密码的方法,原理和绘图界面中那些选项框一致,就是获取前端返回内容,在后端实现一个组件隐藏,另一个组件展示
# 在这里把隐藏密码的输入框叫暗码,显示密码的输入框叫明码
def evt_visiable(self, event):
# 显示密码按钮是否点亮
v = self.m_checkBox1.GetValue()
if v:
# 获取到在暗码中输入的内容,送到明码框里
f = self.m_PassWord.GetValue()
self.m_textCtrl15.SetValue(f)
# 隐藏暗码框
self.m_PassWord.Hide()
# 展示明码框
self.m_textCtrl15.Show()
# 一定不能忘了Layout重新排列
self.Layout()
# 清除暗码框中的内容,方便下一次传值
self.m_PassWord.Clear()
else:
f = self.m_textCtrl15.GetValue()
self.m_PassWord.SetValue(f)
self.m_textCtrl15.Hide()
self.m_PassWord.Show()
self.Layout()
self.m_textCtrl15.Clear()
方法实现。
(二)密码存储方式
1.数据库存储:
我们先打开Navicat,在csdn_text01数据库下新建一个表:
点击保存,命名为password
在其中输入一个默认账号密码:admin和123456
修改后记得点最下面有个小对号,提交操作
此时我们需要读取数据库来读取账号密码,我们只需要更改密码验证方法(validate_credentials方法):
def validate_credentials(self,username,password):
try:
# 以下是数据库存储:
conn = Connection(
host="localhost",
port=3306,
user="root",
password="123456",
db="Csdn_text01"
)
cursor = conn.cursor()
'''这个sql语句是查找与提供的账号密码匹配的数据条数,返回的row是一个包含一个数字的元组,如果成功匹配到一条账号密码,
row[0]=1,即此时只需要判断row[0]是否等于1就可以判断密码是否正确
'''
sql = '''
select count(*)
from password
where user=%s and password=%s
'''
cursor.execute(sql, (username, password))
row = cursor.fetchone()
# print(row)
cnt = row[0]
if cnt != 1:
return False
return True
# 抛出异常只能在文件未打开的时候工作
except FileNotFoundError:
print("Credentials file not found")
return False
此时运行程序可以发现读取及调用正常。
(三)注册界面
根据逻辑来说,用户能注册来用这个系统,说明是开发方允许的,那开发方就会给他一个唯一身份识别码,我们现在先在mysql中开这样一个数据表用来存储这个唯一身份识别码,只有唯一识别码正确,才能成功注册:
同样的新建表:
新建完成后,在里面输入666666,修改后记得点最下面有个小对号,提交操作
此时需要用到wxfb进行界面设计,毕竟是个界面嘛,总得设计一下:
新建一个Dialog,命名为EnrollFrame,自行摆放静态文本框及输入框,给确认绑定事件evt_enroll,给取消绑定事件evt_exit(注意文本框的名字)
写一个继承类,然后在继承类中用代码实现两个事件:
class EnrollFrame(CSDNtext01.EnrollFrame):
def __init__(self):
CSDNtext01.EnrollFrame.__init__(self, parent=None)
# 这个参数是验证密码那个参数,我们告诉系统密码还没输呢
self.status = False
def evt_enroll(self, event):
# 正常的连接数据库及提取出唯一身份识别码操作
conn = Connection(
host="localhost",
port=3306,
user="root",
password="123456",
db="Csdn_text01"
)
cursor = conn.cursor()
cursor.execute("select * from idcheck")
id = cursor.fetchall()
if self.m_idCheck.GetValue() == id[0][0]:
front_username = self.m_textCtrl8.GetValue()
front_password = self.m_textCtrl9.GetValue()
front_password2 = self.m_textCtrl10.GetValue()
if front_password == front_password2:
front_list = [front_username, front_password]
insert_query = ("insert into password(username,password) values (%s,%s)")
cursor.execute(insert_query, front_list)
conn.commit()
else:
wx.MessageBox("请重新输入密码!", "提示信息")
else:
wx.MessageBox("唯一身份识别码错误!", "提示信息")
cursor.close()
conn.close()
self.Close()
wx.MessageBox("注册成功,请重启程序进行登录", "提示信息")
def evt_exit(self, event):
self.Close()
event.Skip()
sys.exit()
此时做好了继承,我们可以直接去和登录界面进行连接了。给登陆界面的注册按键绑定事件evt_enroll,顺手给退出事件绑定evt_exit,然后实现这两个事件:
def evt_enroll(self, event):
self.Close()
event.Skip()
enrollframe = EnrollFrame()
enrollframe.Show()
def evt_exit(self, event):
self.status = False
self.Close()
event.Skip()
sys.exit()
执行注册行为,在数据库里查看发现成功写入,登录也没问题,功能已实现
(四)文件路径直接点击选择功能
在这里就又要写个界面了,进到wxfb,新建一个Dialog,命名为ChoosePathFrame,这里我们需要一个文本框以及一个按钮,在按钮实现选择路径事件。一个窗口只放这么两个东西未免有点单调,我们就把主界面那副图放上去吧:
注意这里选择图片一定要选wxStaticBitmap,别选成wxBitmapButton,把输入框名字改成m_ExcelPath(截图错误)。
给查找绑定事件evt_openfile,给确定绑定事件evt_ok
在后端继承该窗口并写代码实现事件:
class ChoosePathFrame(CSDNtext01.ChoosePathFrame):
def __init__(self):
CSDNtext01.ChoosePathFrame.__init__(self,parent=None)
# 这里我们同样给一个信号,表示文件是否正常打开
self.status = False
# 实现选择路径,这就是一个固定的文件选择器,记着就行
def evt_openfile(self, event):
try:
# 定义文件对话框的文件类型过滤器,就是选择窗口右下角那个文件类型那个东西
wildcard = "Excel (*.xlsx;*.xls)|*.xlsx;*.xls|" \
"All files (*.*)|*.*"
# 创建文件对话框
dlg = wx.FileDialog(
self, message="打开文件",
defaultDir=os.getcwd(),
defaultFile="",
wildcard=wildcard,
style=wx.FD_OPEN |
wx.FD_CHANGE_DIR | wx.FD_FILE_MUST_EXIST |
wx.FD_PREVIEW
)
# 显示文件对话框并获取用户的响应。如果是确定响应,处理数据。
if dlg.ShowModal() != wx.ID_OK:
dlg.Destroy()
event.Skip()
return
# 获取用户选择的文件路径
path = dlg.GetPath()
dlg.Destroy()
# 在界面上设置文件路径
self.m_ExcelPath.SetValue(path)
except:
wx.MessageBox('检查文件是否正确。', '错误信息', wx.OK)
event.Skip()
def evt_ok( self, event ):
# 获取到界面上的路径
filepath = self.m_ExcelPath.GetValue()
# 与数据库建立连接
myconnection = db.MyConnection(filepath)
if not myconnection.excel_connect():
return
self.status = True
self.Close()
event.Skip()
做到这里时会发现调用MyConnection是报错,因为我们之前给该类写的路径是写死了的,没有让外界给他传参,而此时我们要从外界获取路径,这个类就要改,进到db.py中,给__init__方法添加一个filepath参数,修改为:
class MyConnection():
def __init__(self,filepath):
self.filepath=filepath
同时我们在登录类中曾经直接调用过MyConnection类,而此时逻辑不这么走了,应该是在选择路径后调用该类,所以进到登陆类的evt_login方法中将此语句删除。
我们原本的程序逻辑是登陆成功后直接跳转主界面,但此时我们中间写了一个选择文件路径的界面,我们就要把这个界面插进去,到程序的主流程MyAPP类中去,在登陆界面摧毁后加上这样的代码:
choosepath=myframe.ChoosePathFrame()
choosepath.ShowModal()
# 这个status代表文件是否正常打开
if choosepath.status != True:
return False
choosepath.Destroy()
此时执行代码,发现执行无误,在账号正确后确实出现了这样一个窗口:
选择路径功能也是正常的:
(五)界面美化
这里的美化就只将左上角的图标设置以及窗口标题设置,比如我给主窗口加一个图标及标题,就在其继承类的__init__方法中加上:
# 设置图标
# 图片是什么格式,就把第二个参数改成什么格式
icon = wx.Icon("你的图片的路径.png", wx.BITMAP_TYPE_PNG)
self.SetIcon(icon)
# 设置标题
self.SetTitle("村口那座桥")
功能正常实现
(六)关于、帮助的完善
这里也就是之前的重复操作,插静态文本框、图片、自行发挥,一路跟着敲过来的肯定也都会了,自己DIY吧,比如我自己就在关于里面写了这个项目的完成时间什么的,在帮助界面做了一个弹窗:别喊我帮你,我帮不了你。哈哈哈哈哈哈
整个项目:
链接:https://pan.baidu.com/s/1kUH8Sb7asMN_PPznq6RdcA
提取码:665o