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

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

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();
}
}

时间: 2024-10-27 07:11:56

Swing写qq聊天软件(想要QQ表情@我呦)的相关文章

仿QQ聊天软件2.0版

仿QQ聊天软件2.0版 转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907     上次课设做了Java版的仿QQ聊天程序,这次软件实训,我们继续完善了仿QQ聊天程序,将上次未完成及不完善的地方进行完善和改进,还新加了部分功能:表情输入.气泡模式.文件传输.截屏.语音聊天.逐步向QQ的基本功能靠齐.通过这次软件实训,又有了很多收获. 一.设计内容及要求 1.1综述 A.系统概述 我们要做的就是类似QQ这样的面向企业内部的聊天软件,基本功能和QQ类似.首先,

盗qq号软件下载

盗qq号软件下载●●高手QQ:705099868●●以前也在网上找过关于以及怎么破解qq聊天记录密码视频,但是都没有找到好的怎么破解qq聊天记录密码方法.无意中接触到这个人,他是专门帮人查QQ密码,微信密码,查QQ聊天记录,恢复微信记录,通话记录,短信,手机定位等,很讲信誉,技术不错. http://www.155588.com

高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框

上一篇高仿QQ即时聊天软件开发系列之二登录窗口界面写了一个大概的布局和原理 这一篇详细说下拉框的实现原理 先上最终效果图 一开始其实只是想给下拉框加一个placeholder效果,让下拉框在未选择未输入时显示一个提示字符串.由于Background对ComboBox无效,所以直接通过Background来实现是不行了.需要重新写ComboBox的模板,也就是Template,自定义一个模板来实现这个结果.又看了一下QQ的下拉框,这玩意不自定义也难以实现,所以就干脆自定义了. 先上代码,先是Com

亲身体验用Java写的仿qq聊天界面

Java开发工具有许多种,新手用记事本写Java程序,有些人用NetBean,jbuilder,高手用eclipse,下面介绍用eclipse开发qq聊天界面. 代码如下: package Myjava_QQ; import java.awt.*; import javax.swing.*; import Myjava_QQ.truess; import java.awt.event.*; import java.applet.*; import java.io.BufferedReader;

高仿QQ即时聊天软件开发系列之二登录窗口界面

继上一篇高仿QQ即时聊天软件开发系列之一开端之后,开始做登录窗口 废话不多说,先看效果,只有界面 可能还有一些细节地方没有做,例如那个LOGO嘛,不要在意这些细节 GIF虽短,可是这做起来真难,好吧因为我没玩过WPF所以难,因为感觉做出来之后也就那样 整体布局 整体是上下分,下面是左中右分 1 <Grid> 2 <Grid.RowDefinitions> 3 <RowDefinition Height="27"><!--用于放窗口右上角关闭.最

高仿QQ即时聊天软件开发系列之一开端

前段时间在园子里看到一个大神做了一个GG2014IM软件,仿QQ的,那感觉···,赶快下载源码过来试试,还真能直接跑起来,效果也不错.但一看源码,全都给封装到了ESFramework里面了,音视频那部分的源码也给封装到OMCS里面了,这两家伙都是收费的Orz,还能不能好好的看看源码L 大概看了一下GG(为什么每次念这个词都有种怪怪的感觉)的源码,突然想自己也来弄个高仿QQ的软件,平时时间也比较多,就当锻炼吧.别人GG都有个名字,那我也起个名字吧,就叫CC吧 决定了就开始安排 第一个问题,界面框架

搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 (1)

搭建QQ聊天通信的程序:(1)基于 networkcomms.net 创建一个WPF聊天客户端服务器应用程序 原文地址(英文):http://www.networkcomms.net/creating-a-wpf-chat-client-server-application/ 注意:本教程是相当广泛的,如果你是在短请也看到我们的东西 开始和 如何在几分钟内创建一个客户端服务器应用程序教程. 注2:本例中包括,明显延长进一步证明功能,在包中包含的示例 包下载. 在我们开始之前确保您已经安装了Vis

Socket实现仿QQ聊天(可部署于广域网)附源码(1)-简介

1.前言 本次实现的这个聊天工具是我去年c#程序设计课程所写的Socket仿QQ聊天,由于当时候没有自己的服务器,只能在机房局域网内进行测试,最近在腾讯云上买了一台云主机(本人学生党,腾讯云有个学生专享活动一元一个月的云服务器,如果还是学生的可以试一下,地址http://www.qcloud.com/event/qcloudSchool),经过重新编码实现了广域网聊天的功能.下面开始介绍我的自制聊天软件啦!!! 2.功能 1. 聊天室服务器端的创建. 2. 聊天室客户端的创建. 3. 实现客户与

如何把qq聊天工具加入到网站中

自己建立了一个网站,很想和一些访问者实现互动交流,可是没机会.其实,我们可以通过一些聊天软件来实现,如我们熟悉的QQ和雅虎通就可以,下面我们就来介绍一下怎么样实现. 把QQ添加在网站 首先我们登陆QQ,在QQ面板上点击"菜单-设置-个人设置",在弹出的"设置"窗口中点击下面的"生成在线状态"链接(如图1). 图1 QQ中生成在线状态 这时会弹出一个网页,里面有十几种风格样式,选择一个自己喜欢的就可以了,选好后下面输入你的QQ号码.网站名称等内容,