java 聊天界面做出来了 求加入字体改变和表情功能 实在不会做 求大神支招帮忙

&&&&java做的网络聊天室+私聊+发送表情+字体变化+注册处理
&java做的网络聊天室+私聊+发送表情+字体变化+注册处理
java做的网络聊天室,包含客户端与服务器源代码,同时包含聊天室中所用到的图片。
功能实现:
在登录框输入用户名和密码之后,发送到服务器,如果服务器文件中包含这个用户,且密码匹配正确,则正确登录,否则,提示无法登录;
没有用户名,可以向服务器里面进行注册,然后就可以用注册的用户名进行登录
3.密码找回
忘记密码想找回,需输入正确的注册用户名及邮箱。
4.发送表情
聊天界面有选择表情的label,对此label进行了鼠标事件的处理,用到的是QQ表情。
点击用户列表中用户名,可以选择私聊对象。发送的消息只会发送给私聊的对象。
6.查看用户资料
点击聊天界面的查看用户资料checkbox按钮,会向服务器发送查看用户资料的请求,服务器会返回用户对应的资料。
若举报审核通过,可奖励20下载分
被举报人:
举报的资源分:
请选择类型
资源无法下载
资源无法使用
标题与实际内容不符
含有危害国家安全内容
含有反动色情等内容
含广告内容
版权问题,侵犯个人或公司的版权
*详细原因:
VIP下载&&免积分60元/年(1200次)
您可能还需要
Q.为什么我点的下载下不了,但积分却被扣了
A. 由于下载人数众多,下载服务器做了并发的限制。若发现下载不了,请稍后再试,多次下载是不会重复扣分的。
Q.我的积分不多了,如何获取积分?
A. 获得积分,详细见。
完成任务获取积分。
论坛可用分兑换下载积分。
第一次绑定手机,将获得5个C币,C币可。
关注并绑定CSDNID,送10个下载分
下载资源意味着您已经同意遵守以下协议
资源的所有权益归上传用户所有
未经权益所有人同意,不得将资源中的内容挪作商业或盈利用途
CSDN下载频道仅提供交流平台,并不能对任何下载资源负责
下载资源中如有侵权或不适当内容,
本站不保证本站提供的资源的准确性,安全性和完整性,同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
课程资源下载排行
您当前C币:0&&&可兑换 0 下载积分
兑换下载分:&
消耗C币:0&
立即兑换&&
兑换成功你当前的下载分为 。前去下载资源
你下载资源过于频繁,请输入验证码
如何快速获得积分?
你已经下载过该资源,再次下载不需要扣除积分
java做的网络聊天室+私聊+发送表情+字体变化+注册处理
所需积分:5
剩余积分:0
扫描微信二维码精彩活动、课程更新抢先知
VIP会员,免积分下载
会员到期时间:日
剩余下载次数:1000
java做的网络聊天室+私聊+发送表情+字体变化+注册处理
剩余次数:&&&&有效期截止到:
你还不是VIP会员VIP会员享免积分 . 专属通道极速下载
VIP下载次数已满VIP会员享免积分 . 专属通道极速下载,请继续开通VIP会员
你的VIP会员已过期VIP会员享免积分 . 专属通道极速下载,请继续开通VIP会员18246人阅读
01-Java笔记(7)
上一篇是连接,登陆登出和账户管理
连接之后,拿到了connection,通过它可以搞定会话
1.建立一个会话
&textarea cols=&50& rows=&15& name=&code& class=&java&&MessageListener msgListener
= new MessageListener()
public void processMessage(Chat chat, Message message)
if (message != null && message.getBody() != null)
System.out.println(&收到消息:& + message.getBody());
// 可以在这进行针对这个用户消息的处理,但是这里我没做操作,看后边聊天窗口的控制
Chat chat = Client.getConnection().getChatManager()
.createChat(userName, msgListener);
&/textarea&
通过会话发送消息
两个方法,一个直接发送一条文本,一个发送一个Message对象,可包含一些信息,一般使用后者,因为需要包装字体等信息
&textarea cols=&50& rows=&15& name=&code& class=&java&&public static void sendMessage(Chat chat,String message) throws XMPPException {
chat.sendMessage(message);
public static void sendMessage(Chat chat,Message message) throws XMPPException {
chat.sendMessage(message);
&/textarea&
2.消息监听
每个connection的chatManager可以设置一个消息监听器,因为IM必须实现他人对你发起会话也会弹出窗口,即自己可以主动发起会话,也可以接收他人发起的会话
&textarea cols=&50& rows=&15& name=&code& class=&java&&ChatManager manager = Client.getConnection().getChatManager();
manager.addChatListener(new ChatManagerListener() {
public void chatCreated(Chat chat, boolean arg1) {
chat.addMessageListener(new MessageListener() {
public void processMessage(Chat arg0, Message message) {
//若是聊天窗口已存在,将消息转往目前窗口
//若是窗口不存在,开新的窗口并注册
&/textarea&
&& 其实窗口的管理是使用线程的,来一个新的会话,起线程
3.字体表情
在这里实现字体和表情是使用自身开发IM之间的实现。
字体实现思想:
在发送消息的同时,将字体内容作为附加信息发送,接收方接收到根据字体信息进行处理后显示
&& 实现:使用Message对消息进行封装
&textarea cols=&50& rows=&15& name=&code& class=&java&&Message msg = new Message();
msg.setProperty(&size&, size);
msg.setProperty(&kind&, kind);
msg.setProperty(&bold&, bold);
msg.setProperty(&italic&, italic);
msg.setProperty(&underline&, underline);
msg.setProperty(&color&, color);
msg.setBody(getSendInfo());//真正的消息
chat.sendMessage(msg);
&/textarea&
接收方先获取设置信息后展示
&&&&&& 展示的控件: JTextPane receiveText = new JTextPane();
&textarea cols=&50& rows=&15& name=&code& class=&java&&Style style = receiveText.addStyle(&font&, null);
StyleConstants.setFontSize(style, size);
StyleConstants.setFontFamily(style, kind);
StyleConstants.setBold(style, bold);
StyleConstants.setItalic(style, italic);
StyleConstants.setUnderline(style, underline);
StyleConstants.setForeground(style, color);
&/textarea&
&&&&&& 实现机制是客户端本身存有一套表情图片,在选中时,将表情编号加入到消息中,实际发送出去的只是文本,拿到后解析字符串,将编号转为具体表情展示
&&&&& 具体就不写了
1.聊天窗口控制
所谓控制,主要是控制唯一性
无论是你发起一个会话开启一个窗口,还是对方给你发送会话开启,你与对方之间有且仅有一个窗口,之后任何消息都在这个窗口中处理
思想:单例类,持有一个
//现有的聊天窗口
&&& public static TreeMap&String,TelFrame& currentChat = new TreeMap&String,TelFrame&();
其实应该用concurrentHashMap可能会更好,不顾我这边分派的主线程只有一个,不涉及多个线程并发的问题,所以用了Treemap,汗一个,貌似应该hashmap,当时考虑不同
然后,在接收消息的时候根据发消息的用户,判定窗口是否存在,存在,转发消息到该窗口,不存在,建立新的窗口
若是关闭窗口,注销之
&textarea cols=&50& rows=&15& name=&code& class=&java&&//注册聊天室
public static void registerChat(String userName,TelFrame chatroom)
//System.out.println(&注册:&+userName);
currentChat.put(userName, chatroom);
//注销注册
public static void removeChat(String userName)
System.out.println(&用户注销聊天室:&+userName);
currentChat.remove(userName);
//查看是否已有
public static boolean isChatExist(String userName)
return currentChat.containsKey(userName);
//获取对象
public static TelFrame getChatRoom(String userName)
return currentChat.get(userName);
下一篇,主要是用户列表,头像,分组及管理的
&/textarea&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1179723次
积分:11213
积分:11213
排名:第850名
原创:116篇
评论:326条
文章:14篇
阅读:122973
文章:10篇
阅读:33156
文章:18篇
阅读:171372
后续博客都在新地址
blog: http://wklken.me/
邮箱:wklken#yeah.net
微博:凌岳_wkl
My github:
(2)(1)(1)(8)(1)(1)(1)(1)(3)(2)(3)(2)(5)(16)(1)(7)(6)(1)(3)(3)(2)(2)(3)(15)(6)(20)求java聊天室源代码:实现一主机做服务端,实现单人聊天+多人聊天+表情发送。。。。功能_百度知道
求java聊天室源代码:实现一主机做服务端,实现单人聊天+多人聊天+表情发送。。。。功能
我有更好的答案
网上有很多的线程我不太懂
写一个客户端
一个服务器
两个就可以对话了
写一个文件流就可以传文件了
我现在做的就是这种,只不过我想在这个基础上再加上点东西,截屏啊什么的。。。这种类型的代码有吗
有一个 实现了 单聊 私聊 发送文件 截屏 。。。
发送文件的代码是什么啊
就差这个了
额 能给我发下吗 qq:
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁10573人阅读
&用java swing做聊天程序,可能是没事找事,也可能是大才小用
不过作为毕业设计还是绰绰有余了,既然选择了就做吧
其中比较重要的功能可能就是是聊天表情了,当然字体也重要
经过多天来的资料查找和实践,终于做出来了,方法不是很先进,但是运行效果良好
下面是总结出的一个示例
主要功能:
1.聊天表情框的显示,
2.聊天信息(文本信息、字体信息、表情信息、用户)的传输udp,
3.聊天信息的显示(表情和文本混合显示),
5.悬浮提示框
难点1:表情框
难点2:表情(信息)的显示和传输
难点3:表情和文本的混合
难点4:字体属性的设置和传输
&一、表情框
&&&&&&&& 使用javax.swing.JWindow类(无修饰的窗体类),继承这个类可以实现,在一个什么都没有的空窗体(没有标题栏,没有最大、最小化,没有关闭按钮等),我们可以设置其布局为网格布局setLayout(ew&& GridLayout(7,15)&),然后在每个格子里再加上图片(图片当然要先放在JLabel或JPanel里比较好,设置边框,添加鼠标监听)等
代码如下:
&表情图片所在目录:com.zou.chat.qqdefaultface 下放105张表情图& 名字为0.gif,1.gif——104.gif
注意目录结构:com.zou.chat.qqdefaultface 下面放图,com.zou.chat下放java文件,红色标注部分保证一致
PicsJWindow.java:
package com.zou.
java.awt.*;
javax.swing.*;
java.awt.event.*;
&p& Title:
pictures&/p&
&p& Description:
&p& Copyright:
&p& Company:
attributable
PicsJWindow
private static final long serialVersionUID = 1L;
GridLayout
gridLayout1
GridLayout(7,15);
JLabel[105]; /*放表情*/
String[] intro = {&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,
&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,&&,};/*图片描述*/
PicsJWindow(ChatFrame
super(owner);
this.owner=
this.setAlwaysOnTop(true);
(Exception
exception)
exception.printStackTrace();
this.setPreferredSize(new Dimension(28*15,28*7));
JPanel p = new JPanel();
p.setOpaque(true);
this.setContentPane(p);
p.setLayout(gridLayout1);
p.setBackground(SystemColor.text);
String fileName = &&;
for(i=0;i &ico.i++){
fileName= &qqdefaultface/&+i+&.gif&;/*修改图片路径*/
ico[i] =new
JLabel(new
ChatPic(PicsJWindow.class.getResource(fileName),i),SwingConstants.CENTER);
ico[i].setBorder(BorderFactory.createLineBorder(new Color(225,225,225), 1));
ico[i].setToolTipText(i+&&);
ico[i].addMouseListener(new
MouseAdapter(){
mouseClicked(MouseEvent
if(e.getButton()==1){
JLabel cubl = (JLabel)(e.getSource());
ChatPic cupic = (ChatPic)(cubl.getIcon());
owner.insertSendPic(cupic);
cubl.setBorder(BorderFactory.createLineBorder(new Color(225,225,225), 1));
getObj().dispose();
public void mouseEntered(MouseEvent e) {
((JLabel)e.getSource()).setBorder(BorderFactory.createLineBorder(Color.BLUE));
public void mouseExited(MouseEvent e) {
((JLabel)e.getSource()).setBorder(BorderFactory.createLineBorder(new Color(225,225,225), 1));
p.add(ico[i]);
p.addMouseListener(new MouseAdapter(){
public void mouseExited(MouseEvent e) {
getObj().dispose();
public void setVisible(boolean show) {
if (show) {
determineAndSetLocation();
super.setVisible(show);
private void determineAndSetLocation() {
Point loc = owner.getPicBtn().getLocationOnScreen();/*控件相对于屏幕的位置*/
setBounds(loc.x-getPreferredSize().width/3, loc.y-getPreferredSize().height,
getPreferredSize().width, getPreferredSize().height);
}ChatPic.java/*自定义的ImageIcon的子类,在聊天窗体添加表情时,方便取出图片的描述信息*/package com.zou.
import java.net.URL;import javax.swing.ImageI
public class ChatPic extends ImageIcon{
& *图片描述
&private static final long serialVersionUID = 1L;
&//图片代号
&public int getIm() {
&public void setIm(int im) {
&&this.im =
&public ChatPic(URL url,int im){
&&super(url);
&&this.im =
&二、三、四 :表情(信息)的显示和传输,表情和文本的混合 字体属性的设置和传输&
显示表情通过 JTextPane的StyledDocument对象的添加图片功能实现,传输时不直接传图片,只传相对于文本的位置和代号,通过document取出表情的位置和代号,自定义封装规则(这样对方程序收到后就可以在按规则还原位置和代号,在指定位置显示图片),这样表情和文本就可以混合了,字体一样定义传输规则,比如消息串可以这样定义的 userinfo*font*message
用String.spilt()分离
userinfo代表 用户信息字符串表示,为了简单就代表用户名,当然其中不能包括*号,不然 把userinfo*font*message 根据*分离出来就不能取得正确的userinfo,
&font字体信息 font的可为内容为 fontname|fontsize|fontColor&&& ”宋体| 10|1-1-1&,可以继续取出fontname&&&&& fontsize& fontColor&,用其设置要插入的文字的格式
JTextPane的使用:
JTextPane& tp = new JTextPane();
StyledDocument doc = jp.getStyledDocument();//这个对象可以完成下列操作,很方便,实现图文混和显示
既可以插入文本和文本样式,
SimpleAttributeSet attrS//参数需要
&&doc .insertString(doc .getLength(), &Hello,SytedDocument!\n&,attrib.getAttrSet());
&&&&&&public SimpleAttributeSet getAttrSet() {
&&&&&&&&&&&&&& attrSet = new SimpleAttributeSet();
&&&&&&&&&&&&&& StyleConstants.setFontFamily(attrSet, &宋体&);
&&&&&&&&&&&&&& StyleConstants.setBold(attrSet, false);
&&&&&&&&&&&&&&&StyleConstants.setItalic(attrSet, false);
&&&&&&&&&&& &&StyleConstants.setFontSize(attrSet, size);
&&&&&&&& &&&& StyleConstants.setForeground(attrSet, Color.RED);
&&& &&&return attrS
也可以插入图片,
String fileName= &qqdefaultface/1.gif&;
doc .insertIcon(new& ImageIcon(PicsJWindow.class.getResource(fileName)));
还可以设置每次插入的文字位置,
&&&&& int pos = 0;& // 位置0到 长度减1,不要越界
&&&&&doc .setCaretPosition(pos); /*设置插入位置*/
&&& &doc .insertString(doc .getLength(), &Hello,SytedDocument!\n&,attrib.getAttrSet());
图片位置,
&&&&&doc .setCaretPosition(pos);/*设置插入位置*/
doc .insertIcon(new& ImageIcon(PicsJWindow.class.getResource(fileName)));
也可以取出每次插入的文本和图片信息
String text = tp.getText();//取文本
&private List&PicInfo& myPicInfo = new LinkedList&PicInfo&();
&private String buildPicInfo(){
&&StringBuilder sb = new StringBuilder(&&);
&&//遍历jtextpane找出所有的图片信息封装成指定格式
&&& for(int i = 0; i & this.jpMsg.getText().length(); i++){
&&&&&&&&&&&&& if(docMsg.getCharacterElement(i).getName().equals(&icon&)){
&&&&&&&&&&& && //doc = (ChatPic)
&&&&&&&&&&& && Icon icon = StyleConstants.getIcon(doc.getStyledDocument().getCharacterElement(i).getAttributes());
&&&&&&&&&&& && ChatPic cupic = (ChatPic)
&&&&&&&&&&& && PicInfo picInfo= new PicInfo(i,cupic.getIm()+&&);
&&&&&&&&&&& && myPicInfo.add(picInfo);
&&&&&&&&&&& && sb.append(i+&&&+cupic.getIm()+&+&);
&&&&&&&&&&&& }
&&&&&&&&& }
&&& System.out.println(sb.toString());
&&& return sb.toString();
后续代码:ChatFrame.java
package com.zou.
import java.awt.BorderL
import java.awt.C
import java.awt.D
import java.awt.FlowL
import java.awt.F
import java.awt.F
import java.awt.P
import java.ponentA
import java.ponentE
import java.awt.event.MouseE
import java.awt.event.MouseL
import java.awt.event.WindowA
import java.awt.event.WindowE
import java.net.DatagramP
import java.net.DatagramS
import java.net.SocketE
import java.text.SimpleDateF
import java.util.D
import java.util.LinkedL
import java.util.L
import javax.swing.BorderF
import javax.swing.B
import javax.swing.I
import javax.swing.ImageI
import javax.swing.JB
import javax.swing.JComboB
import javax.swing.JC
import javax.swing.JF
import javax.swing.JL
import javax.swing.JOptionP
import javax.swing.JP
import javax.swing.JScrollP
import javax.swing.JTextP
import javax.swing.ScrollPaneC
import javax.swing.UIM
import javax.swing.UnsupportedLookAndFeelE
import javax.swing.plaf.FontUIR
import javax.swing.text.BadLocationE
import javax.swing.text.SimpleAttributeS
import javax.swing.text.StyleC
import javax.swing.text.StyledD
* 聊天窗体类
* @author yangxing zou
* @version 0.1
public class ChatFrame extends JFrame implements MouseListener{
private static final long serialVersionUID = 1L;
public final int fwidth = 550;
public final int fheight = 500;
/* 左边和右边要显示的界面 */
public JLabel left = new JLabel();
JScrollPane jspC
/*聊天内容*/
private JTextPane jpC
/*要发送的内容*/
private JTextPane jpM
JScrollPane jspM
/* 插入文字样式用*/
private StyledDocument docChat =
private StyledDocument docMsg =
private JButton btnS
/*好友的ip*/
/*private String friendIP;*/
/*好友接收消息的端口*/
/*private int friendP*/
/*字体名称;字号大小;文字颜色*/
private JComboBox fontName = null, fontSize = null,fontColor =
/*插入按钮;清除按钮;插入图片按钮*/
private JButton b_shake=null,b_pic, b_remove =
private static final Color TIP_COLOR = new Color(255, 255, 225);
/* 错误信息气泡提示*/
private CoolToolTip error_
/*表情框*/
private PicsJWindow picW
private List&PicInfo& myPicInfo = new LinkedList&PicInfo&();
private List&PicInfo& receivdPicInfo = new LinkedList&PicInfo&();
class PicInfo{
/* 图片信息*/
public PicInfo(int pos,String val){
this.pos =
this.val =
public int getPos() {
public void setPos(int pos) {
this.pos =
public String getVal() {
public void setVal(String val) {
this.val =
public JButton getPicBtn(){
public ChatFrame() {
* 插入图片
* @param icon
public void insertSendPic(ImageIcon imgIc) {
//jpMsg.setCaretPosition(docChat.getLength()); // 设置插入位置
jpMsg.insertIcon(imgIc); // 插入图片
System.out.print(imgIc.toString());
//insert(new FontAttrib()); // 这样做可以换行
* 重组收到的表情信息串
public void receivedPicInfo(String picInfos){
String[] infos = picInfos.split(&[+]&);
for(int i = 0 ; i & infos. i++){
String[] tem = infos[i].split(&[&]&);
if(tem.length==2){
PicInfo pic = new PicInfo(Integer.parseInt(tem[0]),tem[1]);
receivdPicInfo.add(pic);
* 重组发送的表情信息
* @return 重组后的信息串
位置|代号+位置|代号+……
private String buildPicInfo(){
StringBuilder sb = new StringBuilder(&&);
//遍历jtextpane找出所有的图片信息封装成指定格式
for(int i = 0; i & this.jpMsg.getText().length(); i++){
if(docMsg.getCharacterElement(i).getName().equals(&icon&)){
//ChatPic = (ChatPic)
Icon icon = StyleConstants.getIcon(jpMsg.getStyledDocument().getCharacterElement(i).getAttributes());
ChatPic cupic = (ChatPic)
PicInfo picInfo= new PicInfo(i,cupic.getIm()+&&);
myPicInfo.add(picInfo);
sb.append(i+&&&+cupic.getIm()+&+&);
System.out.println(sb.toString());
return sb.toString();
* 初始化窗体
private void init() {
setLayout(new BorderLayout());
/*this.setUndecorated(true);*/
getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
setSize(fwidth, fheight);
this.setMinimumSize(new Dimension(fwidth, fheight));
this.getContentPane().setBackground(Color.GRAY);
setResizable(false);
setLocationRelativeTo(null);
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(1);
this.addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent e) {
ChatFrame.this.picWindow.dispose();
public void componentMoved(ComponentEvent e) {
ChatFrame.this.picWindow.dispose();
public void componentHidden(ComponentEvent e) {
ChatFrame.this.picWindow.dispose();
/*窗体前置*/
setAlwaysOnTop(true);
/*聊天信息框*/
jpChat = new JTextPane();
jpChat.addMouseListener(this);
jpChat.setEditable(false);
jspChat = new JScrollPane(jpChat,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
/*用户聊天信息输入框*/
jpMsg = new JTextPane();
jpMsg.addMouseListener(this);
jspMsg = new JScrollPane(jpMsg,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jspMsg.setPreferredSize(new Dimension(100, 100));
error_tip = new CoolToolTip(this, jspMsg, TIP_COLOR, 3, 10);
/*发送按钮*/
btnSend = new JButton(&发送&);
btnSend.setFocusable(false);
/*获得JTextPane的Document用于设置字体*/
docChat = jpChat.getStyledDocument();
docMsg = jpMsg.getStyledDocument();
/*添加鼠标事件监听*/
btnSend.addMouseListener(this);
/*字体区*/
JLabel lblSend = new JLabel();
lblSend.setLayout(new FlowLayout(FlowLayout.RIGHT));
String[] str_name = { &宋体&, &黑体&, &Dialog&, &Gulim& };
String[] str_Size = { &12&, &14&, &18&, &22&, &30&, &40& };
//String[] str_Style = { &常规&, &斜体&, &粗体&, &粗斜体& };
String[] str_Color = { &黑色&, &红色&, &蓝色&, &黄色&, &绿色& };
fontName = new JComboBox(str_name);
fontSize = new JComboBox(str_Size);
fontColor = new JComboBox(str_Color);
Box box = Box.createHorizontalBox();
box.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
box.add(new JLabel(&字体:&));
box.add(fontName);
box.add(Box.createHorizontalStrut(3));
box.add(new JLabel(&字号:&));
box.add(fontSize);
box.add(Box.createHorizontalStrut(3));
box.add(new JLabel(&颜色:&));
box.add(fontColor);
box.add(Box.createHorizontalStrut(3));
box.add(btnSend);
JPanel PaneLeftSouth = new JPanel();
PaneLeftSouth.setLayout(new BorderLayout());
b_pic = new JButton(&表情&);
b_pic.setFocusable(false);
b_shake = new JButton(&震动&);
b_shake.setFocusable(false);
b_remove = new JButton(&清空&);
b_remove.setFocusable(false);
picWindow = new PicsJWindow(this);
b_pic.addMouseListener(this);
b_remove.addMouseListener(this);
b_shake.addMouseListener(this);
Box box_1 = Box.createHorizontalBox();
box_1.add(b_pic);
box_1.add(b_shake);
box_1.add(b_remove);
PaneLeftSouth.add(box_1, BorderLayout.NORTH);//字体、表情、震动
PaneLeftSouth.add(jspMsg, BorderLayout.CENTER);
PaneLeftSouth.add(box, BorderLayout.SOUTH);
left.setLayout(new BorderLayout());
left.setOpaque(false);
PaneLeftSouth.setBackground(Color.CYAN);
left.add(jspChat, BorderLayout.CENTER);
left.add(PaneLeftSouth, BorderLayout.SOUTH);
add(left, BorderLayout.CENTER);
new receivMsgThread().start();
public void mouseClicked(MouseEvent arg0) {}
public void mouseEntered(MouseEvent arg0) {
error_tip.setVisible(false);
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent e) {
picWindow.setVisible(false);
public void mouseReleased(MouseEvent e) {
if (getY() &= 0) {
setLocation(getX(), 0);
if (e.getButton() != 1)
/*不是左键*/
JComponent source = (JComponent) e.getSource();
/*鼠标释放时在事件源内,才响应单击事件*/
if (e.getX() &= 0 && e.getX() &= source.getWidth() && e.getY() &= 0
&& e.getY() &= source.getHeight()) {
if (source == btnSend){
sendMsg();
}else if (source == this.b_shake){
sendShake();
} else if (source == this.b_pic){
picWindow.setVisible(true);
} else if (source == this.b_remove){
jpChat.setText(&&);
jpChat.revalidate();
* 向好友发送震动
public void sendShake(){
String uname = Sender.localIP+&:&+Sender.SendP
if (!Sender.sendUDPMsg(MsgType.SHAKE, uname, Sender.localIP, Sender.SendPort,&shake&)){
error_tip.setText(&发送失败!&);
error_tip.setVisible(true);
insert(&你向 &+ uname +& 发送了一个震动!&);
* 震动三秒以上
* @param uname
public void shake(String uname){
setExtendedState(Frame.NORMAL);
setVisible(true);
insert(uname+& 给你发了一个震动!&);
new Thread(){
long begin = System.currentTimeMillis();
long end = System.currentTimeMillis();
Point p = ChatFrame.this.getLocationOnScreen();
public void run(){
int i = 1;
while((end-begin)/1000&3){
ChatFrame.this.setLocation(new Point((int)p.getX()-5*i,(int)p.getY()+5*i));
end = System.currentTimeMillis();
Thread.sleep(5);
ChatFrame.this.setLocation(p);
} catch (InterruptedException e) {
e.printStackTrace();
}.start();
* 发送消息
private FontAndText myFont =
public void sendMsg() {
String message = jpMsg.getText();
if (message.length() == 0) {
error_tip.setText(&请输入聊天信息!&);
error_tip.setVisible(true);
if(message.length()&100){
error_tip.setText(&消息最多一百个字符!你要发送的为&+message.length() + &个字符!&);
error_tip.setVisible(true);
String uname = Sender.localIP+&:&+Sender.chatP
myFont = getFontAttrib();
if (Sender.sendUDPMsg(MsgType.CHAT, uname, Sender.localIP, Sender.SendPort,
myFont.toString())) {
addMeg(uname);
this.jpMsg.setText(&&);
error_tip.setText(&发送消息失败!&);
error_tip.setVisible(true);
* 追加新消息到聊天窗体
SimpleDateFormat sf = new SimpleDateFormat(&yyyy-mm-dd HH:mm:ss&);
FontAndText dateFont = new FontAndText(&&,&宋体&,20,Color.BLUE);
public void addMeg(String uname) {
String msg =
uname + & & + sf.format(new Date());
dateFont.setText(msg);
insert(dateFont);
pos2 = jpChat.getCaretPosition();
myFont.setText(jpMsg.getText());
insert(myFont);
insertPics(false);
public void addRecMsg(String uname,String message){
setExtendedState(Frame.NORMAL);
//setVisible(true);
String msg =
uname + & & + sf.format(new Date());
dateFont.setText(msg);
insert(dateFont);/*时间和用户信息*/
int index = message.lastIndexOf(&*&);
System.out.println(&index=&+index);
/*很重要的,记录下聊天区域要插入聊天消息的开始位置,*/
pos1 = jpChat.getCaretPosition();
if(index&0 && index & message.length()-1){/*存在表情信息*/
FontAndText attr = getRecivedFont(message.substring(0,index));
insert(attr);
receivedPicInfo(message.substring(index+1,message.length()));
insertPics(true);
FontAndText attr = getRecivedFont(message);
insert(attr);
* 将收到的消息转化为自定义的字体类对象
* @param message 收到的聊天信息
字体类对象
public FontAndText getRecivedFont(String message){
String[] msgs = message.split(&[|]&);
String fontName = &&;
int fontSize = 0;
String text =
Color fontC = new Color(222,222,222);
if(msgs.length&=4){/*这里简单处理,表示存在字体信息*/
fontName = msgs[0];
fontSize = Integer.parseInt(msgs[1]);
color = msgs[2].split(&[-]&);
if(color.length==3){
int r = Integer.parseInt(color[0]);
int g = Integer.parseInt(color[1]);
int b = Integer.parseInt(color[2]);
fontC = new Color(r,g,b);
text = &&;
for(int i = 3; i & msgs. i++){
text = text + msgs[i];
FontAndText attr = new FontAndText();
attr.setName(fontName);
attr.setSize(fontSize);
attr.setColor(fontC);
attr.setText(text);
System.out.println(&getRecivedFont(String message):&+attr.toString());
* 插入图片
* @param isFriend 是否为朋友发过来的消息
private void insertPics(boolean isFriend) {
if(isFriend){
if(this.receivdPicInfo.size()&=0){
for(int i = 0 ; i & receivdPicInfo.size() ; i++){
PicInfo pic = receivdPicInfo.get(i);
String fileN
jpChat.setCaretPosition(pos1+pic.getPos()); /*设置插入位置*/
fileName= &qqdefaultface/&+pic.getVal()+&.gif&;/*修改图片路径*/
jpChat.insertIcon(new
ImageIcon(PicsJWindow.class.getResource(fileName))); /*插入图片*/
jpChat.updateUI();*/
receivdPicInfo.clear();
if(myPicInfo.size()&=0){
for(int i = 0 ; i & myPicInfo.size() ; i++){
PicInfo pic = myPicInfo.get(i);
jpChat.setCaretPosition(pos2+pic.getPos()); /*设置插入位置*/
String fileN
fileName= &qqdefaultface/&+pic.getVal()+&.gif&;/*修改图片路径*/
jpChat.insertIcon(new
ImageIcon(PicsJWindow.class.getResource(fileName))); /*插入图片*/
/*jpChat.updateUI();*/
myPicInfo.clear();
jpChat.setCaretPosition(docChat.getLength()); /*设置滚动到最下边*/
//insert(new FontAttrib()); /*这样做可以换行*/
* 将带格式的文本插入JTextPane
* @param attrib
private void insert(FontAndText attrib) {
try { // 插入文本
docChat.insertString(docChat.getLength(), attrib.getText() + &\n&,
attrib.getAttrSet());
jpChat.setCaretPosition(docChat.getLength()); // 设置滚动到最下边
} catch (BadLocationException e) {
e.printStackTrace();
private void insert(String text) {
try { // 插入文本
docChat.insertString(docChat.getLength(), text + &\n&,
dateFont.getAttrSet());
jpChat.setCaretPosition(docChat.getLength()); // 设置插入位置
} catch (BadLocationException e) {
e.printStackTrace();
*字体属性辅助类
class FontAndText{
public static final int GENERAL = 0; // 常规
private String msg = &&, name = &宋体&; // 要输入的文本和字体名称
private int size = 0; //字号
private Color color = new Color(225,225,225); // 文字颜色
private SimpleAttributeSet attrSet = // 属性集
* 一个空的构造(可当做换行使用)
public FontAndText() {
public FontAndText(String msg,String fontName,int fontSize,Color color){
this.msg =
this.name = fontN
this.size = fontS
this.color =
* 返回属性集
public SimpleAttributeSet getAttrSet() {
attrSet = new SimpleAttributeSet();
if (name != null){
StyleConstants.setFontFamily(attrSet, name);
StyleConstants.setBold(attrSet, false);
StyleConstants.setItalic(attrSet, false);
StyleConstants.setFontSize(attrSet, size);
if (color != null)
StyleConstants.setForeground(attrSet, color);
return attrS
public String toString(){
//将消息分为四块便于在网络上传播
return name+&|&
+color.getRed()+&-&+color.getGreen()+&-&+color.getBlue()+&|&
public String getText() {
public void setText(String text) {
this.msg =
public Color getColor() {
public void setColor(Color color) {
this.color =
public String getName() {
public void setName(String name) {
this.name =
public int getSize() {
public void setSize(int size) {
this.size =
* 获取所需要的文字设置
* @return FontAttrib
private FontAndText getFontAttrib() {
FontAndText att = new FontAndText();
att.setText(jpMsg.getText()+&*&+buildPicInfo());//文本和表情信息
att.setName((String) fontName.getSelectedItem());
att.setSize(Integer.parseInt((String) fontSize.getSelectedItem()));
String temp_color = (String) fontColor.getSelectedItem();
if (temp_color.equals(&黑色&)) {
att.setColor(new Color(0, 0, 0));
} else if (temp_color.equals(&红色&)) {
att.setColor(new Color(255, 0, 0));
} else if (temp_color.equals(&蓝色&)) {
att.setColor(new Color(0, 0, 255));
} else if (temp_color.equals(&黄色&)) {
att.setColor(new Color(255, 255, 0));
} else if (temp_color.equals(&绿色&)) {
att.setColor(new Color(0, 255, 0));
class receivMsgThread extends Thread{/*接收在线好友和陌生人消息*/
DatagramSocket chatSoc =
public receivMsgThread(){
chatSoc = new DatagramSocket(Sender.chatPort);
} catch (SocketException e) {
e.printStackTrace();
System.exit(1);
public void run(){
while(true){
byte[] bytes=new byte[];
DatagramPacket dp=new DatagramPacket(bytes, bytes.length);
chatSoc.receive(dp);
String recStr = new String(bytes, 0, dp.getLength(), &UTF-8&);
//System.out.println(&GroupsPanel recStr = & + recStr);
String[] strs = recStr.split(&[*]&);
if(strs.length&=3){
msgType = Integer.parseInt(strs[0]);
/*System.out.println(&不是好友发过来的聊天信息!&);*/
String uname = strs[1];
String message = strs[2];
if(strs.length&3){
for(int i = 3; i & strs. i++){
message = message + &*& + strs[i];
if(msgType == MsgType.CHAT){
ChatFrame.this.addRecMsg(uname,message);
}else if(msgType == MsgType.SHAKE){
ChatFrame.this.shake(uname);
} catch (Exception e) {
JOptionPane.showMessageDialog(ChatFrame.this, &系统运行出错!&);
e.printStackTrace();
public static void setUIFont(FontUIResource f) {
/* sets the default font for all Swing components.
ex.setUIFont (new
javax.swing.plaf.FontUIResource(&Serif&,Font.ITALIC,12));*/
java.util.Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get(key);
if (value instanceof FontUIResource)
UIManager.put(key, f);
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
/*和系统的观感保持一致*/
setUIFont(new FontUIResource(&宋体&, Font.PLAIN, 15));
new ChatFrame().setVisible(true);
CoolToolTip.java
package com.zou.
import java.awt.BorderL
import java.awt.C
import java.awt.F
import java.awt.P
import java.ponentA
import java.ponentE
import javax.swing.I
import javax.swing.JD
import javax.swing.JF
import javax.swing.JL
import javax.swing.JLayeredP
import javax.swing.JP
import javax.swing.border.EmptyB
* 气泡提示框类
public class CoolToolTip extends JPanel {
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel();
private boolean haveShowP
private Component attachedC // 要显示提示气泡的组件
private Component parentW // 要显示提示气泡的组件的窗体
public CoolToolTip(Component parent,Component attachedComponent, Color fillColor,
int borderWidth, int offset) {
this.parentWindow =
this.attachedCom = attachedC
label.setBorder(new EmptyBorder(borderWidth, borderWidth, borderWidth,
borderWidth));
label.setBackground(fillColor);
label.setOpaque(true);
label.setFont(new Font(&system&, 0, 12));
setOpaque(false);
// this.setBorder(new BalloonBorder(fillColor, offset));
this.setLayout(new BorderLayout());
add(label);
setVisible(false);
// 当气泡显示时组件移动,气泡也跟着移动
this.attachedCom.addComponentListener(new ComponentAdapter() {
public void componentMoved(ComponentEvent e) {
if (isShowing()) {//悬浮提示 显示了的,重新设置位置
determineAndSetLocation();
private void determineAndSetLocation() {
if(!attachedCom.isShowing()){
Point loc = attachedCom.getLocationOnScreen(); //控件相对于屏幕的位置
Point paPoint = parentWindow.getLocationOnScreen(); //对应窗体相对于屏幕的位置
//System.out.println(attachedComponent.getLocationOnScreen());
setBounds(loc.x-paPoint.x, loc.y -paPoint.y - getPreferredSize().height,
getPreferredSize().width, getPreferredSize().height);
public void setText(String text) {
label.setText(text);
// 设置气泡背景图片
public void setIcon(Icon icon) {
label.setIcon(icon);
// 设置气泡的文字和图片间的距离
public void setIconTextGap(int iconTextGap) {
label.setIconTextGap(iconTextGap);
public void setVisible(boolean show) {
if (show) {
determineAndSetLocation();
findShowPlace();
super.setVisible(show);
private void findShowPlace() {
if (haveShowPlace) {
// we use the popup layer of the top level container (frame or
// dialog) to show the balloon tip
// first we need to determine the top level container
JLayeredPane layeredPane =
if(parentWindow instanceof JDialog){
layeredPane = ((JDialog)parentWindow).getLayeredPane();
}else if(parentWindow instanceof JFrame){
layeredPane = ((JFrame)parentWindow).getLayeredPane();
/*Container parent = attachedCom.getParent();
while (true) {
if (parent instanceof JFrame) {
layeredPane = ((JFrame) parent).getLayeredPane();
} else if (parent instanceof JDialog) {
layeredPane = ((JDialog) parent).getLayeredPane();
parent = parent.getParent();
if(layeredPane!=null){
layeredPane.add(this, JLayeredPane.POPUP_LAYER);
haveShowPlace =
public Component getAttachedComponent() {
return attachedC
public void setAttachedComponent(Component attachedComponent) {
this.attachedCom = attachedC
Sender.java
package com.zou.
import java.io.IOE
import java.net.DatagramP
import java.net.DatagramS
import java.net.InetA
import java.net.InetSocketA
import java.net.S
import java.net.SocketE
import java.net.UnknownHostE
import java.util.R
public class Sender {
/*本机ip*/
public static String localIP = &127.0.0.1&;
/*服务器ip*/
public static String serverIP =
/*错误信息*/
public static String err_msg = &&;
/*默认发送端口*/
public static int SendPort = 5555;
/*默认聊天端口*/
public static int chatPort = 6666;
/*接收信息的socket*/
/*private static DatagramSocket recDs =*/
/*private static DatagramSocket chatSoc =*/
/*rm = new Random();*/
/*setLocalIP();*/
/*chatPort = generateUDPPort();*/
public Sender(){
if(recDs == null){
rePort = generateUsefulPort();
recDs = new DatagramSocket(rePort);
} catch (SocketException e) {
e.printStackTrace();
//findServer();
* @param msgType 消息类别
* @param uname
* @param friendIP
* @param friendPort
* @return 发送是否成功
public static boolean sendUDPMsg(int msgType,String uname,String friendIP,int friendPort,String messae){
/*从命令行得到要发送的内容,使用UTF-8编码将消息转换为字节*/
byte[] msg = (msgType+&*&+uname+&*&+messae).getBytes(&UTF-8&);
/*得到主机的internet地址*/
InetAddress address = InetAddress.getByName(friendIP);
/*用数据和地址初始化一个数据报分组(数据包)*/
DatagramPacket packet = new DatagramPacket(msg, msg.length, address,
friendPort);
/*创建一个默认的套接字,通过此套接字发送数据包*/
DatagramSocket dSocket = new DatagramSocket();
dSocket.send(packet);
/*发送完毕后关闭套接字*/
dSocket.close();
catch (Exception e)
e.printStackTrace();
err_msg = &系统运行异常!&;
* 获取本机的IP
/* private
static void setLocalIP(){
InetAddress address = InetAddress.getLocalHost();
localIP = address.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
err_msg = &出错:SendMessage.takeLocalIP():Exception!&;
System.out.println(&localIP = & + localIP);
/*private static R*/
/* private static int generateUsefulPort(){
= 1025 + rm.nextInt(5000);
bindPort(&0.0.0.0&, port);
bindPort(InetAddress.getLocalHost().getHostAddress(),port);
}catch(Exception e){
e.printStackTrace();
return generateUsefulPort();
System.out.println(&generateUsefulPort=& + port);
/* public static int generateUDPPort(){
rePort = 1024 + rm.nextInt(5000);
DatagramSocket socket = new DatagramSocket(rePort);
socket.close();
} catch (IOException e) {
return generateUDPPort();
return reP
* 检测tcp端口是否可用
* @param host
* @param port
* @throws Exception
/* private static void bindPort(String host, int port) throws Exception{
Socket s = new Socket();
s.bind(new InetSocketAddress(host, port));
s.close();
MsgType.java
package com.zou.
public final class MsgType {
public final static int CHAT = 0;
public final static int ONLINE = 1;
public final static int OFFLINE = 2; //下线
public final static int SHAKE = 3;
运行一个后,改Sender.java,中的&端口,互换端口,运行另一个
&/*默认发送端口*/
&public static int SendPort = 5555;
&/*默认聊天端口*/
&public static int chatPort = 6666;&
如果要带图片的,请到我的资源中下载
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32247次
排名:千里之外
原创:11篇
评论:149条
(1)(1)(1)(1)(3)(1)(2)(1)

我要回帖

更多关于 大神支招 的文章

 

随机推荐