Java模拟qq软件的详细过程
作者:冷丁_ 发布时间:2022-01-27 15:06:19
标签:Java,模拟,qq,界面
目录
登陆界面的实现
登陆界面代码Login类
login的监听类 LoginListener
聊天界面运行图
Client类代码
Server代码
登陆界面代码
**之前在封装代码后出现了问题,按照最初的写法,在登陆完毕后弹出聊天界面后会卡死,原因是当时登陆界面和聊天界面都是使用的主线程,我的代码没有写其他线程,无法多线程运行,因此在弹出聊天界面时线程不够用了,就卡在了监听线程里,因为在监听线程中再有新的监听就会被卡住
在宇哥的指点下,将启动服务器和客户端的部分改为线程,就解决了此问题。改善后的代码简练和清晰了很多,更方便大家参考,代码如下:
**
登陆界面的实现
登陆界面主要使用了JFrame,以及相关的一些组件,并且在界面中加上监听
登陆界面效果图
登陆界面代码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
登陆成功后显示ok,并等待连接
再登陆冷丁的账号,密码为123456
当lding账号登陆成功后完成连接,这时候会弹出两个新的JFram窗口,为聊天见面
随后可以发送消息,消息可以实时显示时间,并显示用户名
一方发送的消息会在另一方的窗口上实时显示出来
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);
}
}
之后会丰富更多功能 敬请期待! 感谢您的观看!!!
来源:https://blog.csdn.net/qq_41359998/article/details/120482564


猜你喜欢
- 在分布式系统架构中,如果一个应用不能对来自依赖的故障进行隔离,那该应用本身就处在被拖垮的风险中。 因此,为了构建稳定、可靠的分布式系统,我们
- 类锁和对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明。一、相关约定为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定
- app中肯定是少不了与用户交互的各种dialog,下面给大家介绍几种提示框的提示。一般创建一个对话框需要经过以下几步:1、创建AlertDi
- 比如有海量的文本文件,如订单,页面点击事件的记录,量特别大,很难搞定。那么我们该怎样解决海量数据的计算?1、获取总行数2、计算每个文件中存多
- 本文实例完成人机猜拳互动游戏的开发,供大家参考,具体内容如下阶段一:实验——分析业务,创建用户类1.分析业务,抽象出类、类的特征和行为2.创
- android studio 新建工程报错Error:Could not resolve all files for configurati
- 目录简单介绍具体实现首先,咱们先配置一下相关的jar包(pom.xml)创建一个Pet接口,存放方法say()创建一个Person类创建一个
- Spring简介和配置学习目标【应用】能够独立完成springIOC的快速入门【应用】能够掌握spring的bean标签的配置【应用】能够独
- 下面是我做C#第一个项目的过程:1.首先打开VS,这里我用的是VS2022预览版,鼠标双击打开VS;图一2.打开VS后会出现下面的页面,鼠标
- 基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后
- 本文实例讲述了C#多线程与跨线程访问界面控件的方法。分享给大家供大家参考。具体分析如下:在编写WinForm访问WebService时,常会
- 场景发布微服务的操作一般都是打完新代码的包,kill掉在跑的应用,替换新的包,启动。spring cloud 中使用eureka为注册中心,
- 前言锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。
- 如果我们在浏览器地址栏乱敲的时候,所敲入的所有未定义的URL都能被程序捕捉到,然后转到一个自制的404错误处理页面。先看效果图登陆页面主页面
- 这篇文章主要介绍了springboot实现文件上传步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 一、使用swing嵌套浏览器要实现的功能:通过java的swing实现在一个窗体中嵌套一个浏览器,可以在这个浏览器中将另一个项目的内容显示出
- 快到过农历年了,微信红包也越来越多了,出现了好多红包 * 程序,就很好奇如何实现的,于是自己研究了一番,亲自写了个微信抢红包的APP。现在就一
- spring mvc @PathVariable / 带斜杠方式获取遇上这个问题,百度google了一下,抄袭里面的内容,可以实现,在此备忘
- 在value目录下,创建styles.xml文件<?xml version="1.0" encoding=&quo
- 1.ArrayList 是基数组结构的,需要连续的内存空间从构造函数可以看出,ArrayList内部用一个Object数组来保存数据。对于无