文章目录
- 项目结构及结果展示
- 代码展示
- Mainframe模块
- RegisterUI模块
- RegisterUI模块
- JDBC模块
大家好,今天用Java的awt组件、swing组件以及数据库JDBC写了一个仿QQ登录的界面,具体演示如下图所示,包括三个页面,分别是登录窗口(Mainframe)、注册窗口(RegisterUI)和忘记密码窗口(ForgetUI)。本文主要应用的技术有:JAVA-GUI、JAVA的awt组件、swing组件、事件处理、JDBC等,是初学者学习和练手的好项目。准备好了吗,let’s get it!
项目结构及结果展示
该项目的结构如下图所示:
主要有三个类:
- Mainframe是登录窗口的GUI类,效果图如下:
- RegisterUI是注册窗口的GUI类,效果图如下:
- ForgetUI是忘记密码窗口的GUI类,效果图如下:
代码展示
在进行代码展示前,先对Swing组件常见的控件类进行介绍,Swing组件常见的控件类有以下几种:
JLabel 标签主要用于展示 文本 或 图片,也可以 同时显示文本和图片
JButton 点击事件
Jtextarea 编辑单行的文本框
JPasswordArea 一个只能输入数字的密码框 把输入的内容用其他字符回显
JTabledPlan 选项卡面板。它允许用户通过点击给定标题或图标的选项卡,在一组组件之间进行切换显示
JCheckBox 复选框,是否被选中
JPanel相当于将整个窗体划分成几个面板,然后在面板中使用布局管理器(管理按钮的布局)一个窗口只能有一个Jframe,能有多个JPlanel
Imagin.SCALE_DEFAULT 自适应JLabel的大小
getScaledInstance 创建此图像的缩放版本。返回一个新的 image 对象,默认情况下,该对象按指定的 width 和 height 呈现图像。即使已经完全加载了初始源图像,新的 image 对象也可以被异步加载
SetIcon图标将会被自动地放到按钮的上面,缺省时居中放置
setborderpainted 如果进度条应该绘制边框,则为 true;否则为 false
Mainframe模块
Mainframe的布局如下图所示:
Mainframe的代码如下:
package frame;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Cursor;import java.awt.GridLayout;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;import javax.swing.BorderFactory;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JPasswordField;import javax.swing.JTextField;public class Mainframe extends Jframe implements ActionListener, FocusListener { private static final long serialVersionUID = 1L; private static final String _txt_account = "QQ密码/手机/邮箱"; private static final String _txt_pwd = "密码"; private static final String _txt_title = "QQ登录"; private static final String _txt_registe = "注册"; private static final String _txt_forget = "忘记密码"; private static final String _txt_blank = ""; private JTextField account; private JPasswordField pwd; private JLabel upper_frame; private JPanel lower_frame, center_frame; private JButton login, register, forget; Mainframe() { //控件的初始化 init(); add(upper_frame, BorderLayout.NORTH); add(center_frame, BorderLayout.CENTER); add(lower_frame, BorderLayout.SOUTH); ImageIcon logo = new ImageIcon("D:/image/logo.jpg"); //左上方小图标 setIconImage(logo.getImage()); setBounds(500, 230, 430, 360); //设定大小及位置 setResizable(false); //登录框大小固定,不允许通过拖、拉改变大小 setDefaultCloseOperation(Jframe.HIDE_ON_CLOSE); //设置窗口右上角的叉号,点击叉号窗口关闭 注意不能EXIT_ON_CLOSE做参数的,用它时候使用的是System.exit方法退出应用程序。故会关闭所有窗口。 setTitle(_txt_title); setVisible(true); //说明数据模型已经构造好了,允许JVM可以根据数据模型执行paint方法开始画图并显示到屏幕上,一般放在最后一句 } public void init() { //账号输入块 account = new JTextField(_txt_account); account.setName("account"); account.setForeground(Color.gray); account.addFocusListener(this); //产生事件响应用户行为 //密码输入块 pwd = new JPasswordField(_txt_pwd); pwd.setName("pwd"); pwd.setForeground(Color.gray); pwd.setEchoChar('0'); //启动后密码框内一定为 “密码” pwd.addFocusListener(this); //注册模块 register = new JButton(_txt_registe); register.setBorderPainted(false); register.setBorder(BorderFactory.createRaisedBevelBorder()); //斜面边框(凸) register.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); register.addActionListener(this); //忘记密码模块 forget = new JButton(_txt_forget); forget.setBorderPainted(false); forget.setBorder(BorderFactory.createRaisedBevelBorder()); forget.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); forget.addActionListener(this); //login按钮模块 login = new JButton(); ImageIcon login_image = new ImageIcon("D:/image/login_image.png"); login_image.setImage(login_image.getImage().getScaledInstance(430, 35, Image.SCALE_DEFAULT)); login.setIcon(login_image); login.setBackground(Color.white); login.setBorderPainted(false); //如果进度条应该绘制边框,则为 true;否则为 false login.setBorder(null); //设置此组件的边框 无 login.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); //将光标设为 “小手”形状 login.addActionListener(this); //qq登录框架上半部分(无按钮之类的内容,只有一张图片) ImageIcon upper_image = new ImageIcon("D:/image/upper_image.png"); upper_image.setImage(upper_image.getImage().getScaledInstance(430, 160, Image.SCALE_DEFAULT)); upper_frame = new JLabel(upper_image); //qq登录中间部分 (账号、密码、 注册、forget) center_frame = new JPanel(); center_frame.setName("center_frame"); center_frame.setLayout(null); center_frame.setLayout(new GridLayout(3, 3, 3, 15)); //这里用到3行3列的空间, 用空格填充 center_frame.add(new JLabel(_txt_blank, JLabel.CENTER)); center_frame.add(account); center_frame.add(new JLabel(_txt_blank, JLabel.CENTER)); center_frame.add(new JLabel(_txt_blank, JLabel.CENTER)); center_frame.add(pwd); center_frame.add(new JLabel(_txt_blank, JLabel.CENTER)); center_frame.add(register); center_frame.add(new JLabel(_txt_blank, JLabel.CENTER)); center_frame.add(forget); center_frame.setBackground(Color.white); //qq登录框架的下半部分login lower_frame = new JPanel(); lower_frame.setName("lower_frame"); lower_frame.setLayout(null); //lower_frame.setLayout(new GridLayout(1, 3, 3, 15)); lower_frame.setLayout(new GridLayout(0, 1)); lower_frame.add(login); } //按钮的点击事件用actionPerformed @Override public void actionPerformed(ActionEvent e){ //处理登录(login)页面 if(e.getSource() == login){ String user_name = account.getText().trim(); String user_pwd = new String(pwd.getPassword()).trim(); if("".equals(user_name)) { JOptionPane.showMessageDialog(null, "请输入帐号!!"); return; } if("".equals(user_pwd)) { JOptionPane.showMessageDialog(null, "请输入密码!!"); return; } } //处理注册(register)页面 if(e.getSource() == register){ RegisterUI registerUI = new RegisterUI(this); } //处理找回密码(forget)页面 if(e.getSource() == forget){ ForgetUI forgetUI = new ForgetUI(this); } } //鼠标的点击或移动之类的用focuslistener @Override public void focusGained(FocusEvent e) { //处理账号输入框 if(e.getSource() == account){ if(_txt_account.equals(account.getText())){ account.setText(""); account.setForeground(Color.BLACK); } } //处理密码输入框 if(e.getSource() == pwd){ if(_txt_pwd.equals(pwd.getText())){ pwd.setText(""); pwd.setEchoChar('*'); pwd.setForeground(Color.BLACK); } } } @Override public void focusLost(FocusEvent e) { //处理账号输入框 if(e.getSource() == account){ if("".equals(account.getText())){ account.setForeground(Color.gray); account.setText(_txt_account); } } //处理密码输入框 if(e.getSource() == pwd){ if("".equals(pwd.getText())){ pwd.setForeground(Color.gray); pwd.setText(_txt_pwd); pwd.setEchoChar('0'); } } } public static void main(String[] args) { Mainframe mainframe = new Mainframe(); }}
RegisterUI模块
RegisterUI的布局和Mainframe的类似,如下图所示:
RegisterUI的代码如下:
package frame;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Cursor;import java.awt.GridLayout;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JTextField;public class RegisterUI extends Jframe implements ActionListener, FocusListener { private static final long serialVersionUID = 1L; private JLabel upper_N, user_name_txt, user_pwd_txt, user_ques_txt, user_ans_txt; //显示文字用 private JButton register_button_S; private JTextField user_name, user_pwd, user_ques, user_ans; //在这里面获取用户输入 private JPanel tmp_South, center_Center; private Mainframe mainframe; //用于关闭登录页面 如果注册成功则将刚开始的注册页面关闭 public RegisterUI(Mainframe mainframe) { this.mainframe = mainframe; //初始化界面 init(); //合成整体 add(center_Center, BorderLayout.CENTER); add(upper_N, BorderLayout.NORTH); add(tmp_South, BorderLayout.SOUTH); //位置、页面大小设置 setSize(250, 400); setLocation(550, 300); ImageIcon logo = new ImageIcon("D:/image/register_image.png"); //左上方小图标 setIconImage(logo.getImage()); setDefaultCloseOperation(Jframe.HIDE_ON_CLOSE); setResizable(false); setVisible(true); } public void init() { //上方图片部分构造 上 即为 北 ImageIcon upper_image = new ImageIcon("D:/image/register_background_image.jpg"); upper_image.setImage(upper_image.getImage().getScaledInstance(250, 139, Image.SCALE_DEFAULT)); upper_N = new JLabel(upper_image); //下方注册图片构造 下 即为 南 tmp_South = new JPanel(); //作为一个容器来放确认注册按钮 register_button_S = new JButton(); ImageIcon conform_register_image = new ImageIcon("D:/image/conform_register_image.png"); conform_register_image.setImage(conform_register_image.getImage().getScaledInstance(220, 40, Image.SCALE_DEFAULT)); register_button_S.setIcon(conform_register_image); // 不绘制边框 register_button_S.setBorderPainted(false); // 设置边框为空 register_button_S.setBorder(null); register_button_S.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); register_button_S.addActionListener(this); //产生事件响应用户行为 tmp_South.add(register_button_S); //中间部分内容 center_Center = new JPanel(); user_name_txt = new JLabel("用户账号", JLabel.CENTER); user_pwd_txt = new JLabel("用户密码", JLabel.CENTER); user_ques_txt = new JLabel("提示问题", JLabel.CENTER); user_ans_txt = new JLabel("问题答案", JLabel.CENTER); user_name = new JTextField(); user_pwd = new JTextField(); user_ques = new JTextField(); user_ans = new JTextField(); user_name.addFocusListener(this); user_pwd.addFocusListener(this); user_ans.addFocusListener(this); user_ques.addFocusListener(this); center_Center.setLayout(new GridLayout(4, 2)); center_Center.add(user_name_txt); center_Center.add(user_name); center_Center.add(user_pwd_txt); center_Center.add(user_pwd); center_Center.add(user_ques_txt); center_Center.add(user_ques); center_Center.add(user_ans_txt); center_Center.add(user_ans); } public void actionPerformed(ActionEvent e) { if (e.getSource() == register_button_S) { String username = user_name.getText().trim(); String password = user_pwd.getText().trim(); String userques = user_ques.getText().trim(); String userans = user_ans.getText().trim(); if ("".equals(username) || username == null) { JOptionPane.showMessageDialog(null, "请输入帐号!!"); return; } if ("".equals(password) || password == null) { JOptionPane.showMessageDialog(null, "请输入密码!!"); return; } if ("".equals(userques) || userques == null) { JOptionPane.showMessageDialog(null, "请输入问题!!"); return; } if ("".equals(userans) || userans == null) { JOptionPane.showMessageDialog(null, "请输入答案!!"); return; } } } //鼠标的点击或移动之类的用focuslistener @Override public void focusGained(FocusEvent e) { //处理账号输入框 if(e.getSource() == user_name){ user_name.setForeground(Color.BLACK); } //处理密码输入框 if(e.getSource() == user_pwd){ user_pwd.setForeground(Color.BLACK); } //处理问题输入框 if(e.getSource() == user_ques){ user_ques.setForeground(Color.BLACK); } //处理答案输入框 if(e.getSource() == user_ans){ user_ans.setForeground(Color.BLACK); } } @Override public void focusLost(FocusEvent e) { //处理账号输入框 if(e.getSource() == user_name){ user_name.setForeground(Color.gray); } //处理密码输入框 if(e.getSource() == user_pwd){ user_pwd.setForeground(Color.gray); } //处理问题输入框 if(e.getSource() == user_ques){ user_ques.setForeground(Color.gray); } //处理答案输入框 if(e.getSource() == user_ans){ user_ans.setForeground(Color.gray); } }}
RegisterUI模块
为了掌握多种布局方式,这里RegisterUI采用的是绝对布局,相关代码如下:
package frame;import java.awt.Color;import java.awt.Cursor;import java.awt.Image;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JTextField;public class ForgetUI extends Jframe implements ActionListener, FocusListener{ private static final long serialVersionUID = 1L; private JLabel upper_N, user_name_txt, user_pwd_txt, user_ques_txt, user_ans_txt, user_ques; //显示文字用 private JButton forget_button_S, submit_button; private JTextField user_name, user_pwd, user_ans; //在这里面获取用户输入 private Mainframe mainframe; //用于关闭登录页面 如果修改密码成功则将刚开始的注册页面关闭 public ForgetUI(Mainframe mainframe) { this.mainframe = mainframe; //页面构造 init(); //合成整体 add(upper_N); add(user_name_txt); add(user_name); add(submit_button); add(user_ques_txt); add(user_ques); add(user_ans_txt); add(user_ans); add(user_pwd_txt); add(user_pwd); add(forget_button_S); //位置、页面大小设置 setSize(270, 430); setLocation(550, 300); setLayout(null); //手工布局 与其他页面不同 ImageIcon logo = new ImageIcon("D:/image/register_image.jpg"); //左上方小图标 setIconImage(logo.getImage()); setDefaultCloseOperation(Jframe.HIDE_ON_CLOSE); setResizable(false); setVisible(true); } public void init() { //上方图片部分构造 上 即为 北 ImageIcon upper_image = new ImageIcon("D:/image/forget_background_image.png"); upper_image.setImage(upper_image.getImage().getScaledInstance(270, 170, Image.SCALE_DEFAULT)); upper_N = new JLabel(upper_image); upper_N.setLocation(0,0); //确定位置 upper_N.setSize(270, 170); //设置大小 //中间部分内容 绝对位置 user_name_txt = new JLabel("用户账号", JLabel.CENTER); user_name_txt.setSize(60, 20); user_name_txt.setLocation(10, 185); submit_button = new JButton(); submit_button.setText("查询"); submit_button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); submit_button.setSize(60, 20); submit_button.setLocation(190, 185); submit_button.addActionListener(this); //产生事件响应用户行为 user_ques_txt = new JLabel("提示问题", JLabel.CENTER); user_ques_txt.setSize(60, 20); user_ques_txt.setLocation(10, 220); user_ans_txt = new JLabel("问题答案", JLabel.CENTER); user_ans_txt.setSize(60, 20); user_ans_txt.setLocation(10, 255); user_pwd_txt = new JLabel("重置密码", JLabel.CENTER); user_pwd_txt.setSize(60, 20); user_pwd_txt.setLocation(10, 290); user_name = new JTextField(); user_name.setSize(100, 30); user_name.setLocation(80, 185); user_ques = new JLabel("点击查询后显示", JLabel.CENTER); user_ques.setSize(100, 30); user_ques.setLocation(80, 220); user_ans = new JTextField(); user_ans.setSize(100, 30); user_ans.setLocation(80, 255); user_pwd = new JTextField(); user_pwd.setSize(100, 30); user_pwd.setLocation(80, 290); user_name.addFocusListener(this); user_pwd.addFocusListener(this); user_ans.addFocusListener(this); //下方注册图片构造 下 即为 南 forget_button_S = new JButton(); ImageIcon conform_register_image = new ImageIcon("D:/image/conform_forget_image.png"); conform_register_image.setImage(conform_register_image.getImage().getScaledInstance(220, 32, Image.SCALE_DEFAULT)); forget_button_S.setIcon(conform_register_image); forget_button_S.setBorderPainted(false); forget_button_S.setBorder(null); forget_button_S.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); forget_button_S.setSize(220, 32); forget_button_S.setLocation(15, 330); forget_button_S.addActionListener(this); //产生事件响应用户行为 } public void actionPerformed(ActionEvent e) { if(e.getSource() == submit_button) { String username = user_name.getText().trim(); if("".equals(username) || username == null) { JOptionPane.showMessageDialog(null, "请输入帐号!!"); return; } else { } } if (e.getSource() == forget_button_S) { if(user_name == null ) { JOptionPane.showMessageDialog(null, "请输入正确账号并点击查询"); return; } String newpwd = user_pwd.getText(); if(newpwd == null || "".equals(newpwd)) { JOptionPane.showMessageDialog(null, "请输入新密码"); return; } String userans = user_ans.getText(); if(userans == null || "".equals(userans)) { JOptionPane.showMessageDialog(null, "请输入答案"); return; } } } //鼠标的点击或移动之类的用focuslistener 这里不知道为啥没变色 (哭 @Override public void focusGained(FocusEvent e) { //处理账号输入框 if(e.getSource() == user_name){ user_name.setForeground(Color.BLACK); } //处理密码输入框 if(e.getSource() == user_pwd){ user_pwd.setForeground(Color.BLACK); } //处理问题输入框 if(e.getSource() == user_ques){ //user_ques.setForeground(Color.BLACK); } //处理答案输入框 if(e.getSource() == user_ans){ user_ans.setForeground(Color.BLACK); } } @Override public void focusLost(FocusEvent e) { //处理账号输入框 if(e.getSource() == user_name){ user_name.setForeground(Color.gray); } //处理密码输入框 if(e.getSource() == user_pwd){ user_pwd.setForeground(Color.gray); } //处理问题输入框 if(e.getSource() == user_ques){ //user_ques.setForeground(Color.gray); } //处理答案输入框 if(e.getSource() == user_ans){ user_ans.setForeground(Color.gray); } }}
JDBC模块
以上仿QQ实现了QQ的登录功能,但是对于登录只做了简单的是否为空的校验,并没有使用数据库进行查询,可以通过以下方式创建并使用数据库进行增删查改:
创建数据库,并创建User表
create database MyQQ;use MyQQ;create table user( id int primary key auto_increment, username varchar(20), password varchar(20), question varchar(100), answer varchar(100));INSERT INTO `USER` VALUES(null,'10001','123456','csdnJava哪家强','每天都要努力的小颓废');
将驱动jar包导入项目(jar包地址在软件地址 的mysql目录):
JDBC操作代码如下:
import com.mysql.jdbc.Driver;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.Statement;public class Test { public static void main(String[] args) throws Exception{ // 需求:查询所有的用户, 输出到控制台 // 分析: // 1.创建项目,拷贝驱动jar包到模块下,并添加到classpath路径中 // 2.注册驱动 DriverManager.registerDriver(new Driver()); // 3.获得连接 String url = "jdbc:mysql://localhost:3306/db_mybatis"; String username = "root"; String password = "root"; Connection connection = DriverManager.getConnection(url,username,password); // 4.创建执行sql的对象 Statement statement = connection.createStatement(); // 5.执行sql语句,处理结果 String sql = "select * from user"; ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()) { // 取出来 //System.out.print(resultSet.getObject("id")+" "); //System.out.print(resultSet.getObject("username")+" "); //System.out.print(resultSet.getObject("password")+" "); //System.out.println(resultSet.getObject("question")+" "); //System.out.println(resultSet.getObject("answer")); System.out.print(resultSet.getObject(1)+" "); System.out.print(resultSet.getObject(2)+" "); System.out.print(resultSet.getObject(3)+" "); System.out.println(resultSet.getObject(4)+" "); System.out.println(resultSet.getObject(5)); System.out.println("------------------------------------------------"); } username = "10001"; password = "1234567"; // 5.2 判断用户名密码是否正确 sql = "select * from user where username = " + username + " and password =" + password; resultSet = statement.executeQuery(sql); //查询到了说明不为空,此时登录成功 if(resultSet.next()){ System.out.println("登录成功"); } else{ System.out.println("登录失败"); } // 6.释放资源 if (resultSet != null){ resultSet.close(); } if (statement != null){ statement.close(); } if (connection != null){ connection.close(); } }}
以上仅演示了简单的JDBC操作,由于篇幅有限,这里暂不介绍如何防登录注入、JDBC工具类的提取以及数据库连接池,后续再进行介绍。
需要注意以上代码中的图片路径使用的是绝对路径,大家可以根据自己需要进行替换,代码已上传至Gitee,如果文章知识点有错误的地方,请指正!大家一起学习,一起进步,谢谢!