在阅读和学习《MATLAB GUI设计学习手册(第2版)》时,发现书中第11章有讲解登录界面实现的例子。在复现示例中密码框的功能时,遇到了以下三个问题:
通过查阅资料,并结合自身的理解,对于上述的三个问题,可给出如下原因
由于MATLAB未设计专门的密码框,加之Edit控件本身的局限性。在实现密码框功能时,便出现了以上的问题。关于密码框的设计,书中所讲述的实现方式依旧能够参考使用。在实现书中讲述的密码框功能后,便自作主张,在Edit控件的KeyPressFcn回调函数中增加了删除所有星号和清空密码的功能。在选中密码框的内容后,按下删除键(Delete)即可删除所有星号和清空密码,其具体代码如下
function password_KeyPressFcn(hObject, eventdata, handles)
% hObject handle to password (see GCBO)
% eventdata structure with the following fields (see MATLAB.UI.CONTROL.UICONTROL)
% Key: name of the key that was pressed, in lower case
% Character: character interpretation of the key(s) that was pressed
% Modifier: name(s) of the modifier key(s) (i.e., control, shift) pressed
% handles structure with handles and user data (see GUIDATA)
c = eventdata.Character; % 获取用户键入的字符
if isstrprop(c, 'graphic') % 键入图形字符执行
%% 多显示一个星号,且将键入的字符存入编辑框password的UserData中
set(handles.password, 'userdata', [get(handles.password, 'userdata'), c],...
'String', [get(handles.password, 'String'), '*']);
else % 键入非图形字符执行
val = double(c); % 获取该字符的ASCII值
if ~isempty(val)
%%% 若键入回车键,执行【登 录】按钮的Callback函数
if val == 13 % 13为回车键ASCII值
Login_Callback(handles.Login, eventdata, handles);
%%% 若键入退格键,清除一个星号,并删除以一位密码
elseif val == 8 % 8为退格键ASCII值
str = get(handles.password, 'userdata');
if ~isempty(str) % 密码不为空执行
str(end) = [];
end
set(handles.password, 'userdata', str);
str2 = get(handles.password, 'String');
if ~isempty(str2) % 星号不为空执行
str2(end) = [];
end
set(handles.password, 'String', str2);
%%% 若键入删除键,删除编辑框内所有星号,清空所有密码字符
elseif val == 127 % 127删除键位ASCII值
set(handles.password, 'String', '');
set(handles.password, 'userdata', '');
end
end
end
虽然在程序中增加了删除所有星号和清空密码的功能,但在使用密码框时仍然具有很多瑕疵。由于光标居中的问题一直存在,即便不用鼠标选中密码框内的所有星号,也可以直接按下删除键删除密码框内的所有星号,并清空键入的密码数据。
除了本书所讲的方法外,还可以采用JPasswordField组件设计密码框。该组件被设计用来处理密码输入,密码文本域会显示一个特殊的输入掩码,而不会回显用户的输入。为了加强此控件的安全性,既不能取消掩码设置,也不能剪切和复制密码组件的内容。JPasswordField组件是一个单行输入组件,继承自JTextField类,因此可以使用JTextField类中的方法,如addActionListener()、removeActionListener()、setHorizontalAlignment()等。其构造器如下表所示
JPasswordField组件不是MATLAB GUIDE中的特有组件,所以在使用此组件设计密码框时,需要在窗口的OpeningFcn函数中进行相关的设置,以下为密码框设计时使用的代码。
jPass = javax.swing.JPasswordField; %% 创建一个密码框
hPass = javacomponent(jPass, [150, 251, 151, 22]); %% 设置密码框的位置
jPass.setHorizontalAlignment(javax.swing.JPasswordField.CENTER); %% 设置密码框输入内容的水平对齐方式
jPass.setFocusable(1); %% 设置焦点table切换次序,matlab 2015b无效
jPass.setEchoChar('*'); %% 设置JPasswordField的回显字符
handles.jPass = jPass; %% 将数据存为GUI数据
handles.hPass = hPass;
关于登录界面的设计方案,可设计多个图形界面;也可采用一个图形界面,充分利用函数的参数传递方法。在此采用多个图形界面实现登录界面的方式进行设计,并采用JPasswordField组件实现密码框。其登录主界面的设计如下
1.窗口的OpeningFcn函数
function Login_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and Login_user data (see GUIDATA)
% varargin command line arguments to SmartTrash_Login (see VARARGIN)
% Choose default command line output for SmartTrash_Login
handles.output = hObject;
set(handles.figure1, 'Name', 'Login')
%%%%%%%%%%%%%%%%%%%%更改界面Logo%%%%%%%%%%%%%%%%%%%%
warning off;
javaFrame = get(hObject, 'JavaFrame');
set(javaFrame, 'FigureIcon', javax.swing.ImageIcon('.\picture\ASCS.png'));
warning on;
%%%%%%%%%%%%%%%%%%%%设置界面背景%%%%%%%%%%%%%%%%%%%%
picture = imread('.\picture\background.jpeg');
image(picture);
set(handles.axes1, 'Visible', 'off', 'colorOrder', [0,0,1], 'units', 'normalized', 'position', [0 0 1 1]);
%%%%%%%%%%%%%%%%%%%%检测注册信息,存在进行加载%%%%%%%%%%%%%%%%%%%%
if exist('Information.mat', 'file')
load Information.mat UserInformation;
setappdata(hObject, 'UserInformation', UserInformation);
end
%%%%%%%%%%%%%%%%%%%% 创建密码框 %%%%%%%%%%%%%%%%%%%%
jPass = javax.swing.JPasswordField; %% 创建一个密码框
hPass = javacomponent(jPass, [221, 233, 159, 30]); %% 设置密码框的位置
jPass.setHorizontalAlignment(javax.swing.JPasswordField.CENTER); %% 设置密码框输入内容的水平对齐方式
jPass.setFocusable(1); %% 设置焦点table切换次序,最新版本无效
jPass.setEchoChar('*'); %% 设置JPasswordField的回显字符
handles.jPass = jPass;
handles.hPass = hPass;
%%%%%%%%%%%%%%%%%%%% 窗口居中 %%%%%%%%%%%%%%%%%%%%
movegui(gcf, 'center');
% Update handles structure
guidata(hObject, handles);
2.登录按钮的Callback函数
function Login_Callback(hObject, eventdata, handles)
% hObject handle to Login (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and Login_user data (see GUIDATA)
if exist('Information.mat', 'file') %% 检测注册信息
% % 获取用户键入的账号和密码
user = get(handles.Login_user, 'String');
password = handles.hPass.Text;
% % 加密用户键入的账号和密码
userTemp = char(user + length(user) + length(password));
passwordTemp = char(password + length(user) + length(password));
% % 读取用户注册信息
UserInformation = getappdata(gcf, 'UserInformation');
users = UserInformation.user;
passwords = UserInformation.password;
% % 查找键入的用户名在注册信息中的位置
index = find(strcmp(users, {userTemp}));
if ~isempty(index) && isequal(passwords{index}, passwordTemp)
close(gcf);
System_Tool;
else
errordlg('账号或密码有误!', '错误');
% % 清空用户名和密码
set(handles.Login_user, 'String', '');
handles.hPass.Text = '';
end
else
msgbox('您尚未注册,请注册后使用!', '提示');
% % 清空用户名和密码
set(handles.Login_user, 'String', '');
handles.hPass.Text = '';
end
注意:代码中出现System_Tool用于打开登录后的主界面,可根据自身需求,替换此函数。
3.注册账号按钮的Callback函数
function Login_register_Callback(hObject, eventdata, handles)
% hObject handle to Login_register (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and Login_user data (see GUIDATA)
box = msgbox('欢迎新用户注册!', '提示');
uiwait(box);
close(gcf);
Register; %% 打开注册界面
4.修改密码按钮的Callback函数
function Login_mpwd_Callback(hObject, eventdata, handles)
% hObject handle to Login_mpwd (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and Login_user data (see GUIDATA)
global name;
global pwd;
if exist('Information.mat', 'file') %% 检测注册信息
% % 获取用户键入的账号和密码
user = get(handles.Login_user, 'String');
password = get(handles.Login_pwd, 'String');
% % 加密用户键入的账号和密码
userTemp = char(user + length(user) + length(password));
passwordTemp = char(password + length(user) + length(password));
% % 读取用户注册信息
UserInformation = getappdata(gcf, 'UserInformation');
users = UserInformation.user;
passwords = UserInformation.password;
% % 查找键入的用户名在注册信息中的位置
index = find(strcmp(users, {userTemp}));
if ~isempty(index) && isequal(passwords{index}, passwordTemp)
% % 存储当前的用户名和密码
name = user;
pwd = password;
box = msgbox('请修改密码!', '提示');
uiwait(box);
close(gcf);
Changepwd; %% 打开修改密码界面
else
errordlg('账号或密码有误!', '错误');
% % 清空用户名和密码
set(handles.Login_user, 'String', '');
handles.hPass.Text = '';
end
else
msgbox('您尚未注册,请注册后使用!', '提示');
end
上图为正确输入账户信息和密码后的界面,还未点击登录按钮,单击登录按钮以后便可进入系统主界面。需要注册时,单击注册账户按钮后即可进入账号注册界面,完成相应的注册工作;修改密码时,需要在输入正确的用户名和密码后,单击修改密码按钮进入修改密码界面,进行密码修改。
————————————————————————————————————————————————————
初来乍到,对JPasswordField相关的知识还不熟。若有大神见此拙作,还望指点一二。有好的建议或文中存在纰漏,可邮件联系:[email protected]