Java模拟qq软件的详细过程

时间:2021-09-15 11:15:20

按照最初的写法,在登陆完毕后弹出聊天界面后会卡死,原因是当时登陆界面和聊天界面都是使用的主线程,我的代码没有写其他线程,无法多线程运行,因此在弹出聊天界面时线程不够用了,就卡在了监听线程里,因为在监听线程中再有新的监听就会被卡住。后将启动服务器和客户端的部分改为线程,就解决了此问题。改善后的代码简练和清晰了很多,更方便大家参考,代码如下:

登陆界面的实现

登陆界面主要使用了JFrame,以及相关的一些组件,并且在界面中加上监听
登陆界面效果图

Java模拟qq软件的详细过程

登陆界面代码Login类

package com.lding.net;

import javax.swing.*;
import java.awt.*;

/**
* @program: Chat
* @description:
* @author: 王丁
* @date: 2021-09-26 08:58
**/
public class Login{
  JTextField jTextField;


  public static void main(String[] args){
      Login login = new Login ();
      login.showUI ("kk");
  }

  public void showUI(String str){
      JFrame jf = new JFrame ();
      jf.setTitle ("❤️DDqq登陆界面❤️");
      jf.setSize (500, 400);
      jf.setDefaultCloseOperation (3);
      jf.setLocationRelativeTo (null);
      jf.setResizable (false);
      FlowLayout fl = new FlowLayout (FlowLayout.CENTER, 5, 5);
      jf.setLayout (fl);
      Dimension dim1 = new Dimension (500, 200);//图片大小
      Dimension dim2 = new Dimension (100, 50);//标签大小
      Dimension dim3 = new Dimension (300, 30);//输入框大小
      Dimension dim4 = new Dimension (100, 40);//按钮大小

      ImageIcon icon = new ImageIcon ("source/Login1.jpg");
      JLabel labimg = new JLabel (icon);
      labimg.setPreferredSize (dim1);
      jf.add (labimg);

      JLabel labuser = new JLabel ();
      labuser.setText ("user:");
      labuser.setPreferredSize (dim2);
      jf.add (labuser);
      JTextField textuser = new JTextField ();
      textuser.setPreferredSize (dim3);
      jf.add (textuser);

      JLabel labpassword = new JLabel ();
      labpassword.setText ("password:");
      labpassword.setPreferredSize (dim2);
      jf.add (labpassword);

      JPasswordField textPassword = new JPasswordField ();
      textPassword.setPreferredSize (dim3);
      jf.add (textPassword);

      JButton button = new JButton ();
      button.setBorder (BorderFactory.createRaisedBevelBorder ());
      button.setText ("login");
      button.setPreferredSize (dim4);
      jf.add (button);
      jf.setVisible (true);

      LoginListener ll = new LoginListener(textuser,textPassword, jf);
      button.addActionListener (ll);
      this.jTextField=ll.jTextField;

  }
}


login的监听类 LoginListener

package com.lding.net;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
* @program: Chat
* @description:
* @author: 王丁
* @date: 2021-09-26 08:59
**/
public class LoginListener implements ActionListener {
  JTextField jTextField;
  JPasswordField jPasswordField;
  JFrame jf ;
  LoginListener( JTextField jTextField,JPasswordField jPasswordField,JFrame jf){
      this.jf=jf;
      this.jTextField = jTextField;
      this.jPasswordField = jPasswordField;
  }
  @Override
  public void actionPerformed(ActionEvent e){
      if(jTextField.getText().equals("Alice")&&String.valueOf(jPasswordField.getPassword()).equals("1234")){
          System.out.println ("服务端登录!!");
          String name =jTextField.getText();
          new Server(name).start();
          jf.dispose();

      }else if(jTextField.getText().equals("Lding")&&String.valueOf(jPasswordField.getPassword()).equals("1234")){

          String name =jTextField.getText();
          System.out.println ("客户端登录!!");
          new Client(name).start();
          jf.dispose();
      }


  }
}

在登陆完毕后,需要跳转到聊天界面,这里采用的方法是通过一个flag标志来判断是否登陆完毕,当登陆完毕后,会创建新的聊天界面,并且登陆页面会被关闭
依然是双端通信,假定一端为客户端,一端为服务端,其实两端都可为用户。

 

聊天界面运行图

先登陆Alice的账号 密码为123456

Java模拟qq软件的详细过程

登陆成功后显示ok,并等待连接

Java模拟qq软件的详细过程

再登陆冷丁的账号,密码为123456

Java模拟qq软件的详细过程

当lding账号登陆成功后完成连接,这时候会弹出两个新的JFram窗口,为聊天见面

Java模拟qq软件的详细过程

随后可以发送消息,消息可以实时显示时间,并显示用户名
一方发送的消息会在另一方的窗口上实时显示出来

Java模拟qq软件的详细过程

Client类代码

package com.lding.net;

import com.lding.ui.MsgUI;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @program: Chat
* @description: 客户端
* @author: 王丁
* @date: 2021-09-26 08:58
**/
public class Client extends  Thread{
  String name;

  public Client(String name) {
      this.name=name;
  }
  public static void main(String[] args) {
      String port="客户端";
      Login login=new Login();
      login.showUI(port);
  }

  @Override
  public void run(){
      try {
          startClient();
      } catch (IOException e) {
          e.printStackTrace ();
      }
  }

  void startClient() throws IOException{
      Socket socket=new Socket("127.0.0.1",8888);
      //输入 输出流对象
      InputStream inputStream=socket.getInputStream();
      OutputStream outputStream=socket.getOutputStream();
      MsgUI msgUI=new MsgUI(outputStream,name);
      JTextPane showmsgpane=msgUI.initUI("客户端");
      outputStream.flush();
      int count=1;
      while(true){
          int msglenth=inputStream.read();
          System.out.println("消息长度:"+msglenth);
          byte[] msgbytes=new byte[msglenth];
          //将接下来的数据读入字节数组中
          inputStream.read(msgbytes);

          count++;
          if(count%2==0){
              SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
              String date = df.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳
              String getmsg=new String(msgbytes);
              String msg=showmsgpane.getText();
              showmsgpane.setText(msg+date+"  ["+getmsg+"]"+"说:"+"\n");
          }else{
              String getmsg=new String(msgbytes);
              String msg=showmsgpane.getText();
              showmsgpane.setText(msg+getmsg+"\n");
          }
      }
  }
}


Server代码

package com.lding.net;

import com.lding.ui.MsgUI;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
* @program: Chat
* @description:
* @author: 王丁
* @date: 2021-09-26 08:58
**/
public class Server extends  Thread{
  JTextField jTextField;
  String name;
  public Server(String name){
      this.name=name;
  }
  public static void main(String[] args) {
      String port="服务端";
      Login login=new Login();
      login.showUI(port);
  }
  @Override
  public void run(){
      try {
          startServer();
      } catch (IOException e) {
          e.printStackTrace ();
      }
  }
  void startServer() throws IOException{
      ServerSocket serverSocket=new ServerSocket(8888);
      System.out.println("等待连接!!");
      Socket clientsocket=serverSocket.accept();//监听连接
      System.out.println("连接成功!!");
      InputStream inputStream=clientsocket.getInputStream();
      OutputStream outputStream=clientsocket.getOutputStream();

      MsgUI msgUI=new MsgUI(outputStream,name);
      JTextPane showmsgpane=msgUI.initUI("服务端");
      //outputStream.flush();
      int count=1;
      while(true){
          int msglenth=inputStream.read();
          System.out.println("消息长度是:"+msglenth);
          byte[] msgbytes=new byte[msglenth];
          //将接下来的数据读入字节数组中
          inputStream.read(msgbytes);
          count++;
          if(count%2==0){
              SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
              String date = df.format(new Date());// new Date()为获取当前系统时间,也可使用当前时间戳
              String getmsg=new String(msgbytes);
              String msg=showmsgpane.getText();
              showmsgpane.setText(msg+date+"  ["+getmsg+"]"+"说:"+"\n");
          }else{
              String getmsg=new String(msgbytes);
              String msg=showmsgpane.getText();
              showmsgpane.setText(msg+getmsg+"\n");
          }
      }
  }
}


登陆界面代码

MsgUI

package com.lding.ui;

import javax.swing.*;
import java.awt.*;
import java.io.OutputStream;

/**
* @program: Chat
* @description:
* @author: 王丁
* @date: 2021-09-26 08:59
**/
public class MsgUI extends JFrame {

  OutputStream outputStream;
  String name;
  public MsgUI(OutputStream outputStream,String name){
      this.outputStream=outputStream;
      this.name=name;
  }
  public JTextPane initUI(String title){
      setTitle(title);
      setSize(800,800);
      setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      setLocationRelativeTo(null);
      setLayout(new FlowLayout());
      //接收显示框
      JTextPane jtp=new JTextPane();
      jtp.setPreferredSize(new Dimension(750,400));
      JScrollPane jsp=new JScrollPane(jtp);
      jtp.getText();
      Dimension dim=new Dimension(750,400);//按钮大小



      //发送框
      JTextPane jtp1=new JTextPane();
      jtp1.setPreferredSize(new Dimension(750,200));
      JScrollPane jsp1=new JScrollPane(jtp1);

      JButton btn=new JButton("发送");
      add(jsp);
      add(jsp1);
      add(btn);
      setVisible(true);

      MsgListener msgl=new MsgListener(jtp1,this.outputStream,name);
      btn.addActionListener(msgl);
      return jtp;
  }
}

MsgUIListener

package com.lding.ui;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.OutputStream;

/**
* @program: Chat
* @description:
* @author: 王丁
* @date: 2021-09-26 09:00
**/
public class MsgListener implements ActionListener {

  JTextPane jtp;
  OutputStream outputStream;
  String name;
  public  MsgListener(JTextPane jtp,OutputStream outputStream,String name){
      this.jtp=jtp;
      this.outputStream=outputStream;
      this.name=name;
  }
  @Override
  public void actionPerformed(ActionEvent e) {
      byte[] names=this.name.getBytes();
      try {
          outputStream.write(names.length);
          outputStream.write(names);
          outputStream.flush();
      } catch (IOException ex) {
          ex.printStackTrace();
      }


      String msg=jtp.getText();
      byte[] msgs=msg.getBytes();
      try {
          outputStream.write(msgs.length);
          outputStream.write(msgs);
          outputStream.flush();
      } catch (IOException ex) {
          ex.printStackTrace();
      }
      jtp.setText(null);
  }
}

到此这篇关于Java模拟qq软件的详细过程的文章就介绍到这了,更多相关Java 模拟 qq内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_41359998/article/details/120482564