15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > java+Oracle+SWT制作简单的聊天室

java+Oracle+SWT制作简单的聊天室

时间:2023-07-22 07:42:01 | 来源:网站运营

时间:2023-07-22 07:42:01 来源:网站运营

java+Oracle+SWT制作简单的聊天室:

1.产品展示

按照互联网行业的惯例,先吹牛。

我们的项目采用了和腾讯QQ一样的设计界面,拥有和腾讯QQ同等优秀的产品设计理念和思路。

1.1这是我们的登录界面







1.2注册账号与找回账号界面







1.3用户主界面







1.4添加好友界面



1.5单聊界面(分为和机器人与真人,左边贴了一张图,不方便展示)













1.6群聊界面













2.细节!!!talk is cheap,show me the code

2.1主页面

2.1.1注册表记住密码

/*** 注册表实现记住密码,注册表在我们的电脑里面,用键值对的方式存取*/ Preferences pre = Preferences.userNodeForPackage(getClass()); // 注册表实现记住密码 pre = Preferences.userNodeForPackage(UserLoginUI.class); pre.put(text_uname.getText(), text_pwd.getText());//存放密码 pre.get(text_uname.getText(), null)//根据键获取密码





2.1.2界面布局







//自定义拖拽事件开始 private int startX;// 记录鼠标移动前的X坐标 private int startY;// 记录鼠标移动前的y坐标 private int lastX;// 记录鼠标移动后的x坐标 private int lastY;// 记录鼠标移动后的y坐标 private boolean isdown;// 记录鼠标是否按下 UserMainUI thisOBJ = this;// 实现窗口拖拉 自己创建自己这个类 /** * 设置指定区域label_topimage窗口移动事件,你要在那个组件上添加拖拽事件就在那里添加,我这里是在label里添加的 */ label_topimage.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { thisOBJ.isdown = true; thisOBJ.startX = e.x; thisOBJ.startY = e.y; } @Override public void mouseUp(MouseEvent e) { thisOBJ.isdown = false; super.mouseUp(e); } }); label_topimage.addMouseMoveListener(new MouseMoveListener() { @Override public void mouseMove(MouseEvent arg0) { if (thisOBJ.isdown) { thisOBJ.lastX = arg0.x; thisOBJ.lastY = arg0.y; int x = thisOBJ.lastX - thisOBJ.startX; int y = thisOBJ.lastY - thisOBJ.startY; org.eclipse.swt.graphics.Point location = shell.getLocation(); int xx = location.x; int yy = location.y; shell.setLocation(x + xx, y + yy); } } });





2.1.3用户主页采用的堆栈式布局StackLayout

主页我们采用的是堆栈式布局,这样就能配合自定义的label按钮的点击事件呈现切换界面的效果

SWT里的Composite面板为我们提供了六种布局方式,分别是

StackLayout堆栈式布局,他是所有的子面板都在堆叠在父面板上,可以通过父面板选在在最上面的那块,但只能看到堆在最上面的那块,可以设计触发事件改变最上面的面板达到切换界面的效果







private StackLayout stackLayoutne;// 堆栈式布局// 采用堆栈式布局 stackLayoutne = new StackLayout(); composite_down.setLayout(stackLayoutne); // 将备选的三块面板层叠放到composite_down主面板下 composite_tree = new Composite_tree(composite_down, SWT.NONE, fromQQ); composite_message = new Composite_message(composite_down, SWT.NONE, fromQQ); composite_weChat = new Composite_weChat(composite_down, SWT.NONE); stackLayoutne.topControl = composite_message;// 将composite_message聊天面板设置为主面板 FormData fd_composite_down = new FormData(); fd_composite_down.bottom = new FormAttachment(0, 673); fd_composite_down.right = new FormAttachment(0, 379); fd_composite_down.top = new FormAttachment(0, 222); fd_composite_down.left = new FormAttachment(0); composite_down.setLayoutData(fd_composite_down); composite_down.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));//事件里面切换面板label_center_center.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { lblNewLabel_center_left.setImage(SWTResourceManager.getImage(UserMainUI.class, "/images/消息_不亮.png")); label_center_center.setImage(SWTResourceManager.getImage(UserMainUI.class, "/images/联系人_亮.png")); label_center_right.setImage(SWTResourceManager.getImage(UserMainUI.class, "/images/空间_不亮.png")); stackLayoutne.topControl = composite_tree;// 将composite_message聊天面板设置为主面板 composite_down.layout();// 重置布局,刷新界面 } });

2.1.4用户主界面里的子面板采用SWT自带的滑动面板ScrolledComposite







这样就可以在以面板为父类的组件增长时自动产生滚动条,如果嫌ScrolledComposite太丑不好看的话,可以自己写一个子类继承ScrolledComposite,重写里面的方法




2.1.5其他界面

其他界面基本上是自定义的Composite,每次用的时候new一个,并通过构造函数传递参数进去







树状结构:




//设置滚动面板 ScrolledComposite scrolledComposite = new ScrolledComposite(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); scrolledComposite.setBounds(0, 0, 380, 496); scrolledComposite.setExpandHorizontal(true); scrolledComposite.setExpandVertical(true); Composite composite_1 = new Composite(scrolledComposite, SWT.NONE); composite_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE)); composite_1.setLayout(new RowLayout(SWT.VERTICAL));// 先将面板设置成行式布局RowLayout,再设置为VERTICAL垂直增长 composite_1.setSize(composite_1.computeSize(SWT.DEFAULT, SWT.DEFAULT)); scrolledComposite.setContent(composite_1); // 这一行代码至关重要,关于自动增长序列,每次判断下是不是超出设定好的大小,超出了自动设置滑动条 scrolledComposite.setMinSize(composite_1.computeSize(SWT.DEFAULT, SWT.DEFAULT));//这里值得注意的是,如果是动态增长Composite里的组件,想要自动增长滚动条必须每次刷新后判断 //-----------------<!--自动增长组件的代码--!>------------------------------------------------------------------ composite_1.layout();// 重置布局,刷新界面 // 超级注意!!!必须重置页面再判断是否增长滚动条,否则会出现无法及时增长滚动条的异常 // 这一行代码至关重要,关于自动增长序列,每次判断下是不是超出设定好的大小,超出了设置滑动条 scrolledComposite_chat.setMinSize(composite_1.computeSize(SWT.DEFAULT, SWT.DEFAULT));eclipse里面组件太多了,网上的资料也很分散不系统,可以看看这本书——>《Eclipse SWT/JFACE 核心应用》 清华大学出版社

2.2Socket编程与多线程

建立实时的通讯软件有很多常用的模式,例如同步阻塞IO(JAVA BIO)、同步非阻塞IO(Java NIO) 、异步阻塞IO(Java NIO)、(Java AIO(NIO.2))异步非阻塞IO,由于临近期末考试,笔者也是边学边用,所以用的是最简单也是在业务层次最不成熟的方案同步阻塞IO(JAVA BIO),关于这些模式B站上面有个很好的课程,黑马程序员-Java的IO模式讲解(AIO&BIO&NIO),期考完后我会去好好看的哈哈哈,我这里写的也很简单,通俗易懂,当然问题也还有很多

2.2.1Socket编程

我这里采用的是TCP协议,总体的思路是每个客户端只需要跟服务器进行聊天,不对用户产生点对点的聊天,由服务器充当中介的角色进行消息的转发。每个客户端在连接服务器的时候会先发送一条消息,通过自己写的简单协议将自己的fromQQ,对方的toQQ和消息message以及信号值传递过去,其中信号值flag用来判断用户是想进行单聊群聊还是和机器人聊天,代码里面写的都很详细,大家可以看看,有问题多多指出一起学习哈

package com.fx.net;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Scanner;import com.yc.util.YcUtil;import com.yc.util.fxNetUtil;/** * 采用TCP协议的服务器,设计思路为当有用户连接上服务器时, * 用一个map将其socket存起来,key为用户qq号,为群聊时,将群聊里所有用户的socket存在list里面 * * @author fx * @time 2021年6月30日08:44:25 * */public class ServiceDemo { /** * 分别用map和qunliao存放不同连接的scoket对象 */ static Map<String, Socket> map = new HashMap<String, Socket>();// 用来存放单人聊天的fromQQ和其socket对象 // 用来放不同对象的map,包含一组socket对象 static volatile List<Socket> list = new ArrayList<Socket>();//用volatile修饰可以使其他线程实时获取到这个变量 public static void main(String[] args) { // 服务器 // 创建一个服务器 System.out.println("++++++++++++++++++++"); System.out.println("腾迅QQ服务器启动"); System.out.println("++++++++++++++++++++"); System.out.println("服务器启动,时间:" + new SimpleDateFormat("yyyy年MM月dd日HH:mm").format(new Date())); // 各种对象用以连接 Scanner inScanner = null; ServerSocket ss = null; Socket socket = null; String message;// 记录客户端发送过来的协议消息 try { ss = new ServerSocket(9999);//占有并开放端口 while (true) { // 创建一个接收连接客户端的对象 9999为开放的端口 socket = ss.accept(); String ip_port = new String(socket.getRemoteSocketAddress().toString()).split("/")[1]; System.out.println("有客户端联接上来了,它是:" + ip_port); // 首先要接受客户端发到的第一句话,包含fromQQ,toQQ,message和flag信号值 inScanner = new Scanner(socket.getInputStream());// 接受收入流里的字节流 message = inScanner.nextLine();//这样接收消息高效且简单 if ("0".equals(YcUtil.objToString(fxNetUtil.getflag(message)))) { // 判断为与机器人聊天 new Thread(new ServiceThread(socket)).start();// new一个机器人的线程与用户交流 } else if ("1".equals(YcUtil.objToString(fxNetUtil.getflag(message)))) { // 判断为单聊,先将socket对象存到map中 map.put(fxNetUtil.getfromQQ(message), socket); // 查找其聊天对象是否在线上,在线上应存在socket对象 if (map.containsValue(map.get(fxNetUtil.gettoQQ(message)))) { // 存在,即通过两个好友的socket对象进行聊天 new Thread(new ServiceThreadsingleChat(map.get(fxNetUtil.gettoQQ(message)), map.get(fxNetUtil.getfromQQ(message)))).start(); } if (map.size() == 2) { // 当有两个用户建立连接后,清空map,为后面用户腾出空间 map.clear(); } } else if ("2".equals(YcUtil.objToString(fxNetUtil.getflag(message)))) { // 判断为群聊,先将此时访问的用户qq和其socket对象存储起来 list.add(socket); // 每个用户进入群聊都开启一个线程进行监控,但list对象共享 new Thread(new ServiceThreadWechat(message, socket)).start(); } } } catch (IOException e) { e.printStackTrace(); } finally {// 关闭所有资源 if (null != socket) { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != ss) { try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } }}

2.2.2接入图灵机器人API,进行机器人聊天

代码是网上东拼西凑的,我就截取来一下爬取到数据里面的有效字段,其他的也搞不懂

package com.fx.http;import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.URL;import java.net.URLConnection;import java.net.URLDecoder;import java.net.URLEncoder;import java.util.List;import java.util.Map;/** * @Author fx * @Date 2021年7月1日09:20:25 */public class HttpTest { static String url = null; static String param = ""; public static String GetUrl(String question) { if (null == question) { question = "衡阳天气怎么样"; } url = "http://api.jisuapi.com/iqa/query?appkey=62958a3a6ef3c56d&question=" + encode(question); String result = "";// 访问返回结果 BufferedReader read = null;// 读取访问结果 try { // 创建url URL realurl = new URL(url + "?" + param); // 打开连接 URLConnection connection = realurl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); read = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); String line;// 循环读取 while ((line = read.readLine()) != null) { result += line; } } catch (Exception e) { e.printStackTrace(); } finally { if (read != null) {// 关闭流 try { read.close(); } catch (Exception e) { e.printStackTrace(); } } } // 截取需要的有效字符 return new String(result).split("/"content/":/"")[1].split("/",/"relquestion/"")[0]; } /** * Unicode编码 * * @param url * @return */ public static String encode(String url) { try { String encodeURL = URLEncoder.encode(url, "UTF-8"); return encodeURL; } catch (UnsupportedEncodingException e) { return "Issue while encoding" + e.getMessage(); } } /** * Unicode解码 * * @param url * @return */ public static String decode(String url) { try { String prevURL = ""; String decodeURL = url; while (!prevURL.equals(decodeURL)) { prevURL = decodeURL; decodeURL = URLDecoder.decode(decodeURL, "UTF-8"); } return decodeURL; } catch (UnsupportedEncodingException e) { return "Issue while decoding" + e.getMessage(); } }}


其他的问题暑假再一一完善叭,仓库里面的代码有很多试错时候留下的初期版本,没时间去掉了!!!写了半个月,现在要好好准备期末考试了

这篇文章我首先是写在我的笔记本上的,哪里写的详细一点,这里是搬运过来的

我的笔记:

源码地址:



关键词:简单

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭