目标:实现汽车保养记录系统的登录界面,包含:
1:登陆的用户名以及密码存储在mysql数据库里面
2:登录时,如果用户名不正确,就在用户名文本框后面显示正确或者错误
3:登录时,如果密码不正确,给出对话框提示
4:检查用户名、密码成功时,登录到系统主界面
5:登录界面实现的效果图如下:
详细的实现过程如下:
1:创建系统数据库以及users数据表
在PC命令行执行如下指令
mysql -u root -p
然后输入password,登录mysql,登陆后的工作界面如下:
成功登录mysql后,在mysql命令行中创建一个database,这个database就是我们整个项目需要连接的数据库,指令如下:
create database login;
use login;
创建并使用database,结果如下就表示成功:
创建database后,在login数据库中创建一个名为users的数据表,指令如下:
create table users (id int, name varchar(20), password varchar(20)) default charset=gbk;
并向数据表中插入一条数据,就是我们的登录账号,以及登录密码
insert into users (id, name, password) values (1, "测试者", "abcdefg");
注意:在创建数据表的时候,如果没有设置数据表字符类型为gbk的话,数据表不支持中文数据输入。
创建成功结果如下:
PS:为简单起见,本设计中的数据都是以明文形式实现的,从安全角度出发,我们的账号、密码等信息最好不要以明文形式存在,在后续的学习中,可以把用户名以及密码计算成散列值等形式,这样,即使别人攻破了数据库系统,也无法取得登录时的用户名以及密码信息。
2:在eclipse中创建一个java project,打开eclipse,选择File->new->java project,如下:
project名称为:CarMaintenanceRecordsProject
点击Finish完成创建
3:实现登录界面
3.1:view & model & Dao
3.1.1:展开工程,在src上右键,选择new->package,创建一个java包,名字为source.view,用来存放系统所有的窗口设计文件,在source.view上右键,选择new->class,创建一个名为Login的java文件,Login.java用来实现登录界面布局
结果如下:
3.1.2:继续在src上右键,选择new->package,创建一个java包,名字为source.model,这个包里面是我们用来实现所有的model的,在source.model上右键,选择new->class,创建一个名为Users的java文件,如下:
3.1.3:由于需要向数据库查询用户名是否正确,因此我们需要实现与mysql数据库通信的功能,在src上右键,选择new->package,创建一个名为source.Dao的java包,然后在source.Dao上右键,选择new->class,创建一个名为UsersDao的java文件,用于实现users连接数据库的操作,接着继续在source.Dao上右键,选择new->class,创建一个名为CommonDao的java文件,用于实现各逻辑操作mysql数据库的公共函数,如下所示:
操作mysql数据库需要添加外部的mysql driver包,添加kysql外部依赖库的步骤如下:
在JRE System Library上右键选择Build Path->Configure Build Path,然后在弹出的界面选择Add External JARs...,在弹出的界面选择mysql driver包,
点击OK按钮后,增加mysql依赖库的结果如下所示:
3.2:java文件的实现
3.2.1:在Users.java文件中,我们主要是创建一个包含用户信息的Users类,这个Users类需要和mysql中的users数据表相对应,实现如下:
package source.model;
public class Users {
private int id;//用户编号
private String name;//用户名
private String password;//用户密码
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getPassord(){
return password;
}
public void setPassword(String password){
this.password = password;
}
public String toString(){
return "Users [id=" + id + ", name=" + name + ", password=" + password
+ "]";
}
}
3.2.2:登录界面的设计
a:在Login.java中我们需要做登录界面的窗口设计,设计的布局主要是在init()函数中实现,
设置窗体的大小,以及设置背景图,实现如下:
Dimension dimension = new Dimension(800, 500);
ImageIcon backgroundImage = new ImageIcon("image/background.jpg");
Image icon = new ImageIcon("image/icon.jpg").getImage();
Users users = new Users();
public Login(){
init();
setUndeorated(true);
setSize(dimension);
setTitle("瑞兴汽贸保养系统-登录界面");
setIconImage(icon);
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void init() {
// TODO Auto-generated method stub
Font f = new Font("宋体", Font.BOLD, 20);
int x= 260, y = 190;
BackgroungJpanl panel = new BackgroungJpanl(dimension, backgroundImage.getImage());
panel.setLayout(null);
add(panel, BorderLayout.CENTER);
}
class BackgroungJpanl extends JPanel{
Dimension d;
Image image;
public BackgroungJpanl(Dimension d, Image image){
this.d = d;
this.image = image;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(image, 0, 0, d.width, d.height, this);
}
}
init()里面实现了一个带有backgroung image的JPanel,效果如下:
b:向主界面中添加账号以及密码文本框,以及登录和重置按钮,以及显示用户名是否正确的label,实现代码如下:
JLabel usernameLabel, passwordLabel, systemLabel, nameOKLabel, nameErrorLabel, loginLabel;
JButton loginButton, resetButton;
public static JTextField textField = new JTextField();
JPasswordField passwordField;
private void init() {
// TODO Auto-generated method stub
Font f = new Font("宋体", Font.BOLD, 20);
int x= 260, y = 190;
BackgroungJpanl panel = new BackgroungJpanl(dimension, backgroundImage.getImage());
panel.setLayout(null);
usernameLabel = new JLabel("用户名:");
usernameLabel.setBounds(x, y, 80, 40);
usernameLabel.setFont(f);
passwordLabel = new JLabel("密 码:");
passwordLabel.setBounds(x, y+60, 110, 40);
passwordLabel.setFont(f);
systemLabel = new JLabel("汽车维修记录");
systemLabel.setFont(new Font("宋体", Font.BOLD, 50));
systemLabel.setBounds(x, y-240, 500, 200);
nameOKLabel = new JLabel(new ImageIcon("image/ok.png"));
nameOKLabel.setBounds(x+230, y-6, 50, 50);
nameOKLabel.setVisible(false);
nameErrorLabel = new JLabel(new ImageIcon("image/error.png"));
nameErrorLabel.setBounds(x+230, y-6, 50, 50);
nameErrorLabel.setVisible(false);
loginLabel = new JLabel("用户登录");
loginLabel.setBounds(x+60, y-170, 300, 200);
loginLabel.setFont(new Font("黑体", Font.BOLD, 35));
textField = new JTextField();
textField.setBounds(x+80, y+8, 150, 30);
textField.addMouseListener(this);
textField.addKeyListener(this);
textField.addFocusListener(this);
passwordField = new JPasswordField();
passwordField.setBounds(x+80, y+66, 150, 30);
passwordField.addMouseListener(this);
passwordField.addFocusListener(this);
loginButton = new JButton("登录");
loginButton.setBounds(x+30, y+150, 80, 40);
loginButton.setFont(f);
loginButton.addActionListener(this);
resetButton = new JButton("重置");
resetButton.setBounds(x+150, y+150, 80, 40);
resetButton.setFont(f);
resetButton.addActionListener(this);
panel.add(usernameLabel);
panel.add(passwordLabel);
panel.add(systemLabel);
panel.add(nameOKLabel);
panel.add(nameErrorLabel);
panel.add(loginLabel);
panel.add(textField);
panel.add(passwordField);
panel.add(loginButton);
panel.add(resetButton);
add(panel, BorderLayout.CENTER);
}
实现效果如下:
到这里,我们基本上完成的登录主界面的样式设计
注意:在实现背景图的时候,paintComponent()函数名字一定要正确,千万不要写成painComponent(),否则一个“t”的差别,就会导致背景图无法显示.......
c: 添加各按钮功能
登录界面包含两个按钮,一个用于登录到系统主界面,一个用于重置用户以及密码文本框中的内容。
重置按钮功能的实现
俗话说“柿子捡软的捏”,重置按钮的功能比较简单,就是清空用户、密码文本框的内容以及不显示判定用户名是否正确的label,实现如下:
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == resetButton){
textField.setText("");
passwordField.setText("");
nameOKLabel.setVisible(false);
nameErrorLabel.setVisible(false);
}
}
登录按钮功能的实现
登录按钮的功能比较复杂,主要有以下功能:
1):如果用户名正确,就在用户名文本框后面提示正确,否则提示错误
2):如果用户名和密码正确就登录到系统主界面
实现代码如下:
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == resetButton){
textField.setText("");
passwordField.setText("");
nameOKLabel.setVisible(false);
nameErrorLabel.setVisible(false);
}
if(e.getSource() == loginButton){
String name = textField.getText().toString();
@SuppressWarnings("deprecation")
String password = passwordField.getText().toString();
users.setName(name);
if(name.equals("")){
JOptionPane.showMessageDialog(this, "请输入用户名", "提示", JOptionPane.ERROR_MESSAGE);
nameOKLabel.setVisible(false);
}else if(password.equals("")){
nameErrorLabel.setVisible(false);
JOptionPane.showMessageDialog(this, "请输入密码", "提示", JOptionPane.ERROR_MESSAGE);
}else if((UsersDao.checkName(users)) != null){
nameErrorLabel.setVisible(false);
users.setPassword(password);
if(UsersDao.check(users) != null){
dispose();
//new MainWindow();
}else{
JOptionPane.showMessageDialog(this, "密码错误");
passwordField.setText("");
}
}else{
JOptionPane.showMessageDialog(this, "不存在");
textField.setText("");
passwordField.setText("");
nameOKLabel.setVisible(false);
nameErrorLabel.setVisible(false);
}
}
}
因为要明确显示向mysql数据库查询用户名的结果以及在点击文本框时候判断输入的用户名是否存在于mysql数据表中,因此需要重写下面的接口:
@Override
public void focusGained(FocusEvent e) {
// TODO Auto-generated method stub
if(e.getSource()==textField&&textField.getText().equals("")){
nameErrorLabel.setVisible(false);
nameOKLabel.setVisible(false);
}
if(e.getSource()==passwordField&&textField.getText().equals("")){
nameErrorLabel.setVisible(false);
nameOKLabel.setVisible(false);
}
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getSource() == textField){
if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE){
if(textField.getText().length() < 2 || textField.getText().equals("")){
nameErrorLabel.setVisible(false);
nameOKLabel.setVisible(true);
}
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
String name = textField.getText().toString();
users.setName(name);
if(e.getSource() == passwordField){
if(!textField.equals("")){
if((UsersDao.checkName(users)) != null){
nameOKLabel.setVisible(true);
nameErrorLabel.setVisible(false);
}else{
nameOKLabel.setVisible(false);
nameErrorLabel.setVisible(true);
}
}
}
}
3.2.3:UsersDao.java以及CommonDao.java的实现
Dao包中的文件主要是完成点击窗口控件后与mysql数据库的交互,因此需要在source.Dao.UsersDao.java中实现checkName()函数和check()函数,用于向mysql检查用户名以及密码是否有效的接口如下:
package source.Dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import source.model.Users;
public class UsersDao {
//检查名字
public static Users checkName(Users users) {
// TODO Auto-generated method stub
Users user = null;
CommonDao dao = new CommonDao();
String checkNameSQL = "select name from users where name=?";
ResultSet checkResult = dao.query(checkNameSQL, users.getName());
try{
if(checkResult.next()){
user = new Users();
user.setName(checkResult.getString("name"));
}
}catch(SQLException e){
e.printStackTrace();
}
return user;
}
//判断姓名,密码是否有效
public static Users check(Users users) {
// TODO Auto-generated method stub
Users user = null;
CommonDao dao = new CommonDao();
String checkInfoSQL = "select * from users where name=? and password=?";
String name = users.getName();
String password = users.getPassord();
System.out.println("name: " + name + "\tpassword: " + password);
ResultSet checkResult = dao.query(checkInfoSQL, name, password);
try{
if(checkResult.next()){
user = new Users();
user.setName(checkResult.getString("name").trim());
user.setPassword(checkResult.getString("password").trim());
}
}catch(SQLException e){
e.printStackTrace();
}
return user;
}
}
UsersDao.java中的接口只负责窗口控件与mysql的交互的封装,具体操作mysql数据库的具体实现需要在source.Dao.CommonDao.java中实现,如下:
package source.Dao;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class CommonDao {
private String driverName = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/login";
private String name = "root";
private String password = "123456";
private Connection con = null;
private static final String SQL = "SELECT * FROM ";
public CommonDao(){
}
public void openConnection(){
try{
Class.forName(driverName);
System.out.println("连接数据库...");
con = DriverManager.getConnection(url, name, password);
}catch(ClassNotFoundException e){
e.printStackTrace();
}catch(SQLException e){
e.printStackTrace();
}
}
public ResultSet query(String sql, Object... objs) {
// TODO Auto-generated method stub
ResultSet result = null;
try{
if(con ==null){
openConnection();
}
System.out.println("连接数据库成功.");
PreparedStatement ps = null;
System.out.println(" 实例化Statement对象...");
//SQL语句注入
ps = con.prepareStatement(sql);
if(objs != null){
for(int i = 0; i < objs.length; i++){
System.out.println(" obj params:" + objs[i]);
ps.setObject(i+1, objs[i]);
}
}
System.out.println(" SQL:" + sql);
result = ps.executeQuery();
}catch(SQLException e){
e.printStackTrace();
}
return result;
}
public void close() {
// TODO Auto-generated method stub
try{
con.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
con = null;
}
}
}
4:登录界面实现的效果
4.1:用户名错误
4.2:用户名正确
4.3:输入密码为空
4.4:输入密码错误
至此,登录界面已经基本上完成了,后面就是需要实现,从登录界面到系统主界面的跳转类
//new MainWindow();
了。