Java网络编程:登录界面 登录验证 以及登录成功的好友界面

引言

   

这部分我们就开始设计这个山寨版的qq了,首先最开始的就是需要一个登录界面,当输入的用户名密码正确之后,就跳转到登录成功的界面,我们这里登录成功之后设计的是显示该用户好友界面,这一串我认为是一个整体,所以就放在了一起来写,可能会造成本文比较长。

 

首先我们来看一下登录界面

 

登录界面

   

我们设计的登录界面如图所示

   

   

分析界面

   

这个界面可以分为三个大的部分,北部的一张图片,qq2003全新体验Q人类,中部的QQ号码,手机号码和Email登录部分,以及下面的三个按钮,中间的QQ号码Label,号码输入框,清除号码按钮,QQ密码Label,密码输入框,忘记密码Label,以及隐身登录,记住密码Checkbox,加上申请密码保护按钮,这九个可以用一个3×3的网络布局来做

   

QQ号码,手机号码和Email登录这三个可以切换的Label可以用JTabbedPane

   

界面编程

   

首先北部组件的那张图片可以是一个JLabel,然后把图片作为参数传入即可

   

jLabel = new JLabel(new ImageIcon("image/tou.gif"));

   

然后将其加入到JFrame的北部

   

this.add(jLabel, "North");

   

然后南部组件的三个按钮可以是将三个JButton放在一个JPanel

   

jPanel = new JPanel();

jPanelButton1 = new JButton(new ImageIcon("image/denglu.gif"));

jPanelButton1.addActionListener(this);

jPanelButton2 = new JButton(new ImageIcon("image/quxiao.gif"));

jPanelButton3 = new JButton(new ImageIcon("image/xiangdao.gif"));

jPanel.add(jPanelButton1);

jPanel.add(jPanelButton2);

jPanel.add(jPanelButton3);

this.add(jPanel, "South");

   

中部的组件比较复杂,主要要实现可以切换标签页

   

首先我们把3×3网格里的东西做出来

   

jPanel1 = new JPanel(new GridLayout(3, 3));

jPanel1_JLabel1 = new JLabel("QQ号码", JLabel.CENTER);

jPanel1_JLabel2 = new JLabel("QQ密码", JLabel.CENTER);

jPanel1_JLabel3 = new JLabel("忘记密码");

jPanel1_JLabel4 = new JLabel("申请密码保护");

jPanel1_JButton = new JButton(new ImageIcon("image/clear.gif"));

jPanel1_UserNameField = new JTextField();

jPanel1_PasswordField = new JPasswordField();

jPanel1_CheckBox1 = new JCheckBox("隐身登录");

jPanel1_CheckBox2 = new JCheckBox("记住密码");

jPanel1.add(jPanel1_JLabel1);

jPanel1.add(jPanel1_UserNameField);

jPanel1.add(jPanel1_JButton);

jPanel1.add(jPanel1_JLabel2);

jPanel1.add(jPanel1_PasswordField);

jPanel1.add(jPanel1_JLabel3);

jPanel1.add(jPanel1_CheckBox1);

jPanel1.add(jPanel1_CheckBox2);

jPanel1.add(jPanel1_JLabel4);

   

然后我们除了QQ号码这个标签页已经做好了之外(jPanel1),我们把后面两个标签页(手机号码和Email相应的标签页也做好)

   

jPanel2 = new JPanel();

jPanel3 = new JPanel();

   

最后我们创建一个JTabbedPane把这三个JPanel放进去即可

   

jTabbedPane = new JTabbedPane();

jTabbedPane.add("QQ号码", jPanel1);

jTabbedPane.add("手机号码", jPanel2);

jTabbedPane.add("Email", jPanel3);

this.add(jTabbedPane, "Center");

   

至此登录界面就做好了,接下来就是QQ好友界面

   

QQ好友界面

   

我们设计的QQ好友界面如下图所示

   

   

分析界面

   

这个界面大概可以分为三个部分,最上面的我的好友,可以是一个Button,连着中间的好友列表,好友列表要实现向下拉的功能,可以用一个JScrollPane实现,最下面是两个Button,可以放在一个2×1的网格布局里

   

//用于放我的好友这个界面的东西,布局为BorderLayout

friendPanel1=new JPanel(new BorderLayout());

//用于显示好友列表

friendPanel2=new JPanel(new GridLayout(50, 1, 4, 4));

//用于放陌生人、黑名单按钮

friendPanel3=new JPanel(new GridLayout(2,1));

   

//将我的好友按钮放入friendPanel1

friendPanel_Button1=new JButton("我的好友");

friendPanel1.add(friendPanel_Button1,"North");

   

//将好友列表放入friendPanel1

//给好友列表初始化,用一个JLabel数组放好友列表,每一个好友是一个JLabel

JLabel[] friendsList;

friendsList=new JLabel[50];

for (int i = 0; i < friendsList.length; i++) {

friendsList[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);

//将每个JLabel放入friendPanel2

friendPanel2.add(friendsList[i]);

}

//将friendPanel2放入JScrollPane

friendPanel_jScrollPane=new JScrollPane(friendPanel2);

//将好友列表也就是JScrollPane放入friendPanel1

friendPanel1.add(friendPanel_jScrollPane,"Center");

   

//将南部的两个按钮放入friendPanel1

friendPanel_Button2=new JButton("陌生人");

friendPanel_Button3=new JButton("黑名单");

friendPanel3.add(friendPanel_Button2);

friendPanel3.add(friendPanel_Button3);

friendPanel1.add(friendPanel3,"South");

   

陌生人界面

   

另外我们想实现的是当点击陌生人按钮时能切换到陌生人界面

   

   

如何才能实现呢,一个简单的方式就是我们仿照好友界面也要定义这么多的组件

   

//用于放陌生人这个界面的东西,布局为BorderLayout

   

msrPanel1=new JPanel(new BorderLayout());

   

首先北部现在变为了两个按钮的网格部分的Panel

   

msrPanel3=new JPanel(new GridLayout(2,1));

   

//将这个Panel放入msrPanel1

msrPanel_Button1=new JButton("我的好友");

msrPanel_Button2=new JButton("陌生人");

msrPanel3.add(msrPanel_Button1);

msrPanel3.add(msrPanel_Button2);

msrPanel1.add(msrPanel3,"North");

   

中部依旧是一个JScrollPane用于显示陌生人列表

   

msrPanel2=new JPanel(new GridLayout(20, 1, 4, 4));

JLabel[] msrList=new JLabel[20];

for (int i = 0; i < msrList.length; i++) {

msrList[i]=new JLabel(i+1+"",new ImageIcon("image/mm.jpg"),JLabel.LEFT);

msrPanel2.add(msrList[i]);

}

msrPanel_jScrollPane=new JScrollPane(msrPanel2);

msrPanel1.add(msrPanel_jScrollPane,"Center");

   

最后是南部的一个黑名单按钮

   

msrPanel_Button3=new JButton("黑名单");

msrPanel1.add(msrPanel_Button3,"South");

   

到这里为止我们遇到了一个困难,就是如何在这两个界面中来回切换呢

   

这里我们要将JFrame本身的布局设置为CardLayout

   

cl=new CardLayout();

this.setLayout(cl);

   

然后将我的好友,陌生人加入到这个卡片布局中

   

this.add(friendPanel1,"1");

this.add(msrPanel1,"2");

   

然后我们要在我的好友界面监听陌生人这个按钮,当按下的时候我们切换到陌生人界面

也要在陌生人界面中监听我的好友这个按钮,当按下时我们切换到我的好友界面

   

if (e.getSource()==friendPanel_Button2) {

cl.show(this.getContentPane(), "2");

}

if (e.getSource()==msrPanel_Button1) {

cl.show(this.getContentPane(), "1");

}

   

实现鼠标放在好友上面异色显示

   

也是用到鼠标的监听事件,Entered事件Exited事件

   

public void mouseEntered(MouseEvent e) {

// TODO Auto-generated method stub

JLabel jLabel=(JLabel) e.getSource();

jLabel.setForeground(Color.red);

}

public void mouseExited(MouseEvent e) {

// TODO Auto-generated method stub

JLabel jLabel=(JLabel) e.getSource();

jLabel.setForeground(Color.black);

}

   

登录验证

   

接下来我们要实现登录界面输入用户名和密码,通过验证用户名和密码来达到用户登录验证的功能,所以我们需要一个服务器端来做这件事情。

   

首先是服务器的界面,服务器端的界面设计如下,我们仅仅需要通过GUI开启和关闭服务器即可

   

服务器界面

   

   

分析界面

   

界面的设计代码也很简单,就是用一个JPanel把两个button给装起来即可,然后再构造函数中去初始化这些组件

   

JPanel jPanel;

JButton jButton1, jButton2;

public MyServerFrame() {

jPanel = new JPanel();

jButton1 = new JButton("启动服务器");

jButton1.addActionListener(this);

jButton2 = new JButton("关闭服务器");

jPanel.add(jButton1);

jPanel.add(jButton2);

this.add(jPanel);

this.setSize(300, 200);

this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

this.setVisible(true);

}

   

服务器GUI中的button添加监听事件

   

jButton1.addActionListener(this);

   

public void actionPerformed(ActionEvent e) {

if (e.getSource()==jButton1) {

new MyQQServer();

}

}

   

服务器的GUI设计好了,那么接下来我们真正的来编写服务器端的代码,客户端要向服务器端发送用户名和密码信息,这里服务器和客户端的通信通过对象流的方式传递对象信息,所以首先我们得有对象流传送对象信息的先备知识,这里穿插一下这个知识的讲解

   

对象流

   

服务器端接收

public class MyServer {

public MyServer()

{

System.out.println("3456端口监听,,");

ServerSocket ss=new ServerSocket(3456);

Socket s=ss.accept();

//以对象流的形式读取

ObjectInputStream ois=new ObjectInputStream(s.getInputStream());

User u=(User)ois.readObject();

//输出

System.out.println(u.getName()+u.getPass());

}

}

客户端发送

public class MyClient {

public MyClient()

{

Socket s=new Socket("127.0.0.1",3456);

//通过ObjectOutputStream给服务器传送对象

ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());

User u=new User();

u.setName("桑阳");

u.setPass("123");

oos.writeObject(u);

}

}

其中User类我们在服务器和客户端中都要建立,那么我们选择建立在一个名叫common的包中,该类要实现序列化接口

   

User类

   

public class User implements java.io.Serializable{

private String name;

private String pass;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPass() {

return pass;

}

public void setPass(String pass) {

this.pass = pass;

}

}

   

有了对象流的概念之后,我们就可以真正的来编写用户验证的代码了

   

登录验证

   

用户验证的逻辑就是在登录界面点击了登录按钮,要将用户名框中的信息和密码框中的信息组成一个User类,用对象流的方法传递到服务器端,进行验证。所以首先需要响应按钮的点击事件

   

响应登录点击事件

   

响应登录点击事件的逻辑就是,点击了登录按钮,会去新建一个QQClientUser类,该类中有一个验证用户的方法,而该方法实际上会去调用QQClientConServer类中的sendLoginInfoToServer

   

public class QqClientUser {

   

public boolean checkUser(User u)

{

return new QqClientConServer().sendLoginInfoToServer(u);

}

}

   

QQClientConServer中我们建立与服务器的连接,在我们把用户对象发送到服务器之后,就开始等待服务器端发回来的结果,结果由信息类型表示,当信息类型为1的时候,表示验证通过,这里我们需要定义一个信息类型类MessageType.class,由于这个也是客户端和服务器端要公用的,所以也放在common包下,注意这个是个接口

   

public interface MessageType {

public String message_success="1";

public String message_failure="2";

public String message_common_message="3";

public String message_require_friendOnline="4";

public String message_return_friendOnline="5";

}

   

然后需要建立message类,用于创建服务器和客户端之间传送的对象

   

public class Message implements Serializable {

private String mesType;

private String sender;

private String getter;

private String content;

private String sentTime;

//一大堆setget方法

}

   

   

于是在服务端验证,如果用户密码正确,就返回messageType1

   

if (user.getPasswdString().equals("123456")) {

message.setMesType("1");

oosStream.writeObject(message);

   

//单开一个线程,让该线程与一个客户端保持通信

ServerToClientThread serverToClientThread=new ServerToClientThread(socket);

ManageClientThread.addClientThread(user.getUserID(), serverToClientThread);

serverToClientThread.start();

//并通知所有的其他用户

serverToClientThread.notifyOther(user.getUserID());

}else {

message.setMesType("2");

oosStream.writeObject(message);

socket.close();

}

   

   

public class QqClientConServer {

//发送第一次请求

public boolean sendLoginInfoToServer(Object o)

{

boolean b=false;

Socket s=new Socket("127.0.0.1", 9999);

ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());

oos.writeObject(o);

   

ObjectInputStream ois=new ObjectInputStream(s.getInputStream());

   

Message ms=(Message)ois.readObject();

if(ms.getMesType().equals("1"))

{

b=true;

}

return b;

}

}

   

public void actionPerformed(ActionEvent arg0) {

//如果用户点击登录

if(arg0.getSource()==jp1_jb1)

{

QqClientUser qqClientUser=new QqClientUser();

User u=new User();

u.setUserId(jp2_jtf.getText().trim()); //trim是出去开始或结尾的空格

u.setPasswd(new String(jp2_jpf.getPassword()));

if(qqClientUser.checkUser(u))

{

new QqFriendList();

//关闭掉登录界面

this.dispose();

}else{

JOptionPane.showMessageDialog(this, "用户名密码错误");

}

}

}

   

   

服务器端

   

public class MyQQServer {

public MyQQServer(){

ServerSocket ss=new ServerSocket(9999);

while (true) {

Socket socket=ss.accept();

//接收客户端发来的信息

ObjectInputStream oiStream=new ObjectInputStream(socket.getInputStream());

User user=(User) oiStream.readObject();

System.out.println("接收到用户名:"+user.getUserID()+"密码:"+user.getPasswdString());

Message message=new Message();

ObjectOutputStream oosStream=new ObjectOutputStream(socket.getOutputStream());

if (user.getPasswdString().equals("123456")) {

message.setMesType("1");

oosStream.writeObject(message);

//单开一个线程,让该线程与一个客户端保持通信

ServerToClientThread serverToClientThread=new ServerToClientThread(socket);

ManageClientThread.addClientThread(user.getUserID(), serverToClientThread);

serverToClientThread.start();

//并通知所有的其他用户

serverToClientThread.notifyOther(user.getUserID());

}else {

message.setMesType("2");

oosStream.writeObject(message);

socket.close();

}

System.out.println("服务器启动完毕");

}

}

   

posted @ 2015-05-22 19:45  keedor  阅读(4185)  评论(0编辑  收藏  举报