//主要实现页面等功能的实现

package com.zou.chat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.FontUIResource;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
/**
* 聊天窗体类
* @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 jspChat;
/*聊天内容*/
private JTextPane jpChat;
/*要发送的内容*/
private JTextPane jpMsg;
JScrollPane jspMsg;
/* 插入文字样式就靠它了*/
private StyledDocument docChat = null;
private StyledDocument docMsg = null;

private JButton btnSend;
/*好友的ip*/
/*private String friendIP;*/
/*好友接收消息的端口*/
/*private int friendPort;*/
/*字体名称;字号大小;文字颜色*/
private JComboBox fontName = null, fontSize = null,fontColor = null;
/*插入按钮;清除按钮;插入图片按钮*/
private JButton b_shake=null,b_pic, b_remove = null;
private static final Color TIP_COLOR = new Color(255, 255, 225);
/* 错误信息气泡提示*/
private CoolToolTip error_tip;
/*表情框*/
private PicsJWindow picWindow;
private List<PicInfo> myPicInfo = new LinkedList<PicInfo>();
private List<PicInfo> receivdPicInfo = new LinkedList<PicInfo>();
class PicInfo{
/* 图片信息*/
int pos;
String val;
public PicInfo(int pos,String val){
this.pos = pos;
this.val = val;
}
public int getPos() {
return pos;
}
public void setPos(int pos) {
this.pos = pos;
}
public String getVal() {
return val;
}
public void setVal(String val) {
this.val = val;
}

}
public JButton getPicBtn(){
return b_pic;
}
public ChatFrame() {
init();
}
/**
* 插入图片
*
* @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.length ; 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)icon;
PicInfo picInfo= new PicInfo(i,cupic.getIm()+"");
myPicInfo.add(picInfo);
sb.append(i+"&"+cupic.getIm()+"+");
}
}
System.out.println(sb.toString());
return sb.toString();
//return null;
}

/**
* 初始化窗体
*/
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() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(1);
}

});
this.addComponentListener(new ComponentAdapter(){

@Override
public void componentResized(ComponentEvent e) {
ChatFrame.this.picWindow.dispose();
}

@Override
public void componentMoved(ComponentEvent e) {
ChatFrame.this.picWindow.dispose();
}

@Override
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();
}
@Override
public void mouseClicked(MouseEvent arg0) {}
@Override
public void mouseEntered(MouseEvent arg0) {
error_tip.setVisible(false);
}
@Override
public void mouseExited(MouseEvent arg0) {}
@Override
public void mousePressed(MouseEvent e) {
picWindow.setVisible(false);
}
@Override
public void mouseReleased(MouseEvent e) {
if (getY() <= 0) {
setLocation(getX(), 0);
}
if (e.getButton() != 1)
return;/*不是左键*/

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.SendPort;
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();
try {
Thread.sleep(5);
i=-i;
ChatFrame.this.setLocation(p);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
/**
* 发送消息
*/
private FontAndText myFont = null;
public void sendMsg() {
String message = jpMsg.getText();
if (message.length() == 0) {
error_tip.setText("请输入聊天信息!");
error_tip.setVisible(true);
return;
}
if(message.length()>100){
error_tip.setText("消息最多一百个字符!你要发送的为"+message.length() + "个字符!");
error_tip.setVisible(true);
return;
}

String uname = Sender.localIP+":"+Sender.chatPort;
myFont = getFontAttrib();
if (Sender.sendUDPMsg(MsgType.CHAT, uname, Sender.localIP, Sender.SendPort,
myFont.toString())) {
addMeg(uname);
this.jpMsg.setText("");
} else {
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);
}else{
FontAndText attr = getRecivedFont(message);
insert(attr);
}
}
/**
* 将收到的消息转化为自定义的字体类对象
* @param message 收到的聊天信息
* @return 字体类对象
*/
public FontAndText getRecivedFont(String message){
String[] msgs = message.split("[|]");
String fontName = "";
int fontSize = 0;
String[] color;
String text = message;
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.length ; 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());
return attr;
}
/**
* 插入图片
*
* @param isFriend 是否为朋友发过来的消息
*/
int pos1;
int pos2;
private void insertPics(boolean isFriend) {

if(isFriend){
if(this.receivdPicInfo.size()<=0){
return;
}else{
for(int i = 0 ; i < receivdPicInfo.size() ; i++){
PicInfo pic = receivdPicInfo.get(i);
String fileName;
jpChat.setCaretPosition(pos1+pic.getPos()); /*设置插入位置*/
fileName= "qqdefaultface/"+pic.getVal()+".gif";/*修改图片路径*/
jpChat.insertIcon(new ImageIcon(PicsJWindow.class.getResource(fileName))); /*插入图片*/
/* jpChat.updateUI();*/
}
receivdPicInfo.clear();
}
}else{

if(myPicInfo.size()<=0){
return;
}else{
for(int i = 0 ; i < myPicInfo.size() ; i++){
PicInfo pic = myPicInfo.get(i);
jpChat.setCaretPosition(pos2+pic.getPos()); /*设置插入位置*/
String fileName;
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 = null; // 属性集
/**
* 一个空的构造(可当做换行使用)
*/

public FontAndText() {
}
public FontAndText(String msg,String fontName,int fontSize,Color color){
this.msg = msg;
this.name = fontName;
this.size = fontSize;
this.color = color;
}

/**
* 返回属性集
*
* @return
*/
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 attrSet;
}
public String toString(){
//将消息分为四块便于在网络上传播
return name+"|"
+size+"|"
+color.getRed()+"-"+color.getGreen()+"-"+color.getBlue()+"|"
+msg;
}
public String getText() {
return msg;
}

public void setText(String text) {
this.msg = text;
}

public Color getColor() {
return color;
}

public void setColor(Color color) {
this.color = color;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getSize() {
return size;
}

public void setSize(int size) {
this.size = 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));
}
return att;
}

private class receivMsgThread extends Thread{/*接收在线好友和陌生人消息*/
DatagramSocket chatSoc = null;
public receivMsgThread(){
try {
chatSoc = new DatagramSocket(Sender.chatPort);
} catch (SocketException e) {
e.printStackTrace();
System.exit(1);
}
}
@Override
public void run(){
while(true){
try {
byte[] bytes=new byte[1024*128];
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("[*]");
int msgType;
if(strs.length>=3){
msgType = Integer.parseInt(strs[0]);
}else{
System.out.println("不是好友发过来的聊天信息!");
continue;
}
String uname = strs[1];

String message = strs[2];
if(strs.length>3){
for(int i = 3; i < strs.length ; 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);
}
}

//聊天图片处理

package com.zou.chat;
import java.net.URL;

import javax.swing.ImageIcon;
public class ChatPic extends ImageIcon{
/**
*图片描述
*/
private static final long serialVersionUID = 1L;
int im;//图片代号

public int getIm() {
return im;
}
public void setIm(int im) {
this.im = im;
}
public ChatPic(URL url,int im){
super(url);
this.im = im;
}
}

//气泡等显示框架

package com.zou.chat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
/**
* 气泡提示框类
*/
public class CoolToolTip extends JPanel {
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel();
private boolean haveShowPlace;
private Component attachedCom; // 要显示提示气泡的组件
private Component parentWindow; // 要显示提示气泡的组件的窗体
public CoolToolTip(Component parent,Component attachedComponent, Color fillColor,
int borderWidth, int offset) {
this.parentWindow = parent;
this.attachedCom = attachedComponent;
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() {
@Override
public void componentMoved(ComponentEvent e) {
if (isShowing()) {//悬浮提示 显示了的,重新设置位置
determineAndSetLocation();
}
}
});
}
private void determineAndSetLocation() {
if(!attachedCom.isShowing()){
return;
}
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);
}
@Override
public void setVisible(boolean show) {
if (show) {
determineAndSetLocation();
findShowPlace();
}
super.setVisible(show);
}
private void findShowPlace() {
if (haveShowPlace) {
return;
}
// 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 = null;
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();
break;
} else if (parent instanceof JDialog) {
layeredPane = ((JDialog) parent).getLayeredPane();
break;
}
parent = parent.getParent();
}
if(layeredPane!=null){
layeredPane.add(this, JLayeredPane.POPUP_LAYER);
haveShowPlace = true;
}
}
public Component getAttachedComponent() {
return attachedCom;
}
public void setAttachedComponent(Component attachedComponent) {
this.attachedCom = attachedComponent;
}
}

//主要用于上下线

package com.zou.chat;
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; //震动
}

//加入聊天表情

package com.zou.chat;
import java.awt.*;

import javax.swing.*;

import java.awt.event.*;
/**
* <p> Title: pictures</p>
*
* <p> Description: </p>
*
* <p> Copyright: Copyright (c) 2011 </p>
*
* <p> Company: </p>
*
* @author not attributable
* @version 1.0
*/
public class PicsJWindow extends JWindow {
private static final long serialVersionUID = 1L;
GridLayout gridLayout1 = new GridLayout(7,15);
JLabel[] ico=new JLabel[105]; /*放表情*/
int i;
ChatFrame owner;
String[] intro = {"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",
"","","","","","","","","","","","","","","",};/*图片描述*/
public PicsJWindow(ChatFrame owner) {
super(owner);
this.owner=owner;
try {
init();
this.setAlwaysOnTop(true);
}
catch (Exception exception) {
exception.printStackTrace();
}
}
private void init() throws Exception {
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.length;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(){
public void mouseClicked(MouseEvent e){
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();
}
}
@Override
public void mouseEntered(MouseEvent e) {
((JLabel)e.getSource()).setBorder(BorderFactory.createLineBorder(Color.BLUE));
}
@Override
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(){
@Override
public void mouseExited(MouseEvent e) {
getObj().dispose();
}

});
}
@Override
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);
}
private JWindow getObj(){
return this;
}

}

//通过流建立连接

package com.zou.chat;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Random;
public class Sender {
/*本机ip*/
public static String localIP = "127.0.0.1";
/*服务器ip*/
public static String serverIP = null;
/*错误信息*/
public static String err_msg = "";
/*默认发送端口*/
public static int SendPort = 5555;
/*默认聊天端口*/
public static int chatPort = 6666;
/*接收信息的socket*/
private static DatagramSocket recDs = null;
private static DatagramSocket chatSoc = null;
static int report;
static{
rm = new Random();
setLocalIP();
chatPort = generateUDPPort();
}
public Sender(){
try {
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){
try
{
/*从命令行得到要发送的内容,使用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 = "系统运行异常!";
return false;
}
return true;
}
/**
* 获取本机的IP
*/
private static void setLocalIP(){
try {
InetAddress address = InetAddress.getLocalHost();
localIP = address.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
err_msg = "出错:SendMessage.takeLocalIP():Exception!";
}
System.out.println("localIP = " + localIP);
}
private static Random rm;
private static int generateUsefulPort(){
int port = 1025 + rm.nextInt(5000);
try{
bindPort("0.0.0.0", port);
bindPort(InetAddress.getLocalHost().getHostAddress(),port);
}catch(Exception e){
e.printStackTrace();
return generateUsefulPort();
}
System.out.println("generateUsefulPort=" + port);
return port;
}
public static int generateUDPPort(){
report = 1024 + rm.nextInt(5000);
try {
DatagramSocket socket = new DatagramSocket(report);
socket.close();
} catch (IOException e) {
return generateUDPPort();
}
return report;
}
/**
* 检测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();
}
}

转载于:https://www.cnblogs.com/liteng/p/130a.html

Swing写qq聊天软件(想要QQ表情@我呦)相关推荐

  1. 仿QQ聊天软件(登录界面、好友界面、聊天界面)-Java(Swing、Socket)

    文章目录 一.项目结构 二.项目功能 三.制作界面 (一).登录界面的制作 (二).好友列表界面 (三).聊天界面 四.制作服务器 五.设计通信协议 六.项目缺点 学习了socket通信后,就想来制作 ...

  2. 仿QQ聊天软件(JavaFX+云端数据库)

    仿QQ聊天软件(JavaFX+云端数据库) 这个项目是这学期(大二上学期学完Java后的期末项目),寒假闲着无聊就整理下发上来供大家学习以及参考啦(因为国内关于JavaFX的各种资料感觉都太浅了,本来 ...

  3. 转载:仿QQ聊天软件2.0版

    仿QQ聊天软件2.0版 这是大神的地址:牟尼的专栏 http://blog.csdn.net/u012027907 详细的过程本人没看,但是看见他的实现效果,相当诱人!     上次课设做了Java版 ...

  4. linux qq多进程客户端,基于多进程QQ聊天软件设计.doc

    基于多进程QQ聊天软件设计 基于多进程的QQ聊天程序设计功能需求描述用户名登陆聊天,人与人之间交流是必不可少的.私聊,与特定的用户聊天群聊,向所有的用户发送消息,大家一起聊欢乐多 server端 输入 ...

  5. QQ聊天粘贴的文字变成表情的解决方法

    QQ聊天粘贴的文字变成表情的解决方法 解决方法: 在从事java开发过程中,有时会使用qq给同事发一下带有特殊符号的内容,例如代码啊,文件路径啊等等.发现复制并粘贴到qq聊天窗口时,有的字符竟然变成了 ...

  6. 悄悄说--一个Swing界面的仿qq聊天软件

    1.项目简介 一个仿QQ聊天的软件,实现了用户注册,登录,私聊,创建群组进行多人聊天 2.功能描述 用户进行注册自己的用户名,密码,以及个人简介,然后进行登录 当用户注册成功时,会弹出一个注册成功提示 ...

  7. java仿qq思路_java仿QQ聊天软件OIM艰辛之路(开源项目)

    既然QQ能仿ICQ, 咱java也来个仿QQ. 在我刚学完java后,就想做点什么项目锻炼下自己的技能.凑巧的是,我一个同样学java的朋友在做一个仿qq的项目,不过他做的实在太丑了. 然后他想让我也 ...

  8. java仿QQ聊天软件OIM艰辛之路

    既然QQ能仿ICQ, 咱java也来个仿QQ. 在我刚学完java后,就想做点什么项目锻炼下自己的技能.凑巧的是,我一个同样学java的朋友在做一个仿qq的项目,不过他做的实在太丑了. 然后他想让我也 ...

  9. 初学java之模拟QQ聊天软件(简单实现)

    引言:这个程序是自从学习java以来写的第一个比较大的图形界面程序,花费了大约一周的时间,作为期末的课程设计,也算是基本上完成了任务,当然由于作者的编程能力有限,代码中难免存在BUG,不太简练,今天搬 ...

最新文章

  1. OpenShift — Overview
  2. 一个下课的时间带你手写promise!
  3. 译文 | 与TensorFlow的第一次接触 第六章:并发
  4. 偏置面命令_UG10.0同步建模之移动面、删除面、替换面详解
  5. 数据结构学习(1):单链表
  6. 《编码的奥秘》记录(二)
  7. SWFUpload文件上传
  8. python 函数 与 open打开文件的三种模式:r读、w写、a追加、
  9. 用Python物理建模的第一本书终于来啦
  10. TI飞控出现联系方式,Ti飞控芯片锁了解决办法
  11. VFS中的read/write系统调用
  12. MySQL自定义函数和存储过程
  13. python实现北京租房信息计算
  14. 自动更新网站底部 Copyright © 年份,减少网站维护工作量
  15. 自动驾驶定位技术-马尔科夫定位
  16. C++程序编译-链接-加载过程初探-符号表
  17. 逃避条件作用和回避条件作用,两者的区别是?|小白心理-312/347考研答疑
  18. Kubernetes 最新版本安装过程和注意事项
  19. 警告: com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@40bb7f0a -- Acquisition Attempt Failed
  20. 一篇了解算力相关问题

热门文章

  1. word 代码_怎样在Word 中插入 C/C++ 代码
  2. 用python画出圣诞树_【闲趣】如何用python画出一棵圣诞树
  3. pythonredis实例_Python读写Redis数据库操作示例
  4. c++ enum 给定类型_在 Rust 中创建 C/C++ API
  5. 通过url路径下载服务器文件
  6. CSS3实现文字描边的2种方法
  7. php去除两个重复,php – 如何从两个数组中删除重复对?
  8. mysql 组内排名_【原】MySQL分组排序(包含组内排名、求中位数)
  9. oracle 插入时if,关于sql:ORACLE:如果不存在则插入行-重复键错误
  10. html可折叠边栏,html – 仅使用CSS的可折叠灵活宽边栏