摘要:本文详细介绍一个AWT版本的java聊天软件的开发过程,并着重分析如何用AWT组件实现软件的个性化界面。
简介
本Java聊天软件,纯粹基于AWT组件,没有使用任何Swing组件。在本程序中,我开发了自己的Tab控件和图像画布并给出完整的源码分析。软件实现界面见下图:
软件特点
1)用本文传递笑脸图片
2)私人聊天功能
3)基于定制颜色的良好界面
4)音频功能
描述
在软件中,实现了服务器端模块与客户端模块。在服务器端,我定义了自己的RFC命令。在该应用程序中用到的命令有:
HELO - 初始化到服务器的连接
QUIT - 用户退出聊天室
KICK - 禁止参预聊天
CHRO - 更换聊天室
MESS - 发送普通信息
PRIV - 发送私人信息
ROCO - 取得指定聊天室的聊天人数
CALL - 邀请语音聊天(本文示例中没有包括)
服务器端模块设计
在本模块中,我想解释以下几点:
·建立一个定制的UserObject类,该类包含了如用户名,用户套接字,聊天室名称等等详细的客户端信息。
·当服务器端运行时,它在端口1436(当然我们也可以修改)开通服务器端套接字,听候客户端的连接。如果客户连接上服务器,它将开通一个独立的服务线程。这样,当客户发送"QUIT"命令时,它就会关掉该线程。详见源文件ChatCommunication.java中的细节编程。
下面的示例代码实现了从聊天室客户端获取连接并创建一个新的ChatCommunication对象的功能。在类ChatCommunication中,我们将创建一个专门线程来负责监守来自客户端的所有命令并作出相应的回答。
//ChatServer.java
…………
while(true)
{
Socket socket = serversocket.accept();
ChatCommunication chat = new ChatCommunication(socket);
}
.........
//ChatCommunication.java
..........
ChatCommuncation(Socket socket)
{
personalsocket = sokcet;
dout = new Dataoutputstream(personalsocket.getoutoutstream());
.....
}
客户端模块设计
在本模块中,我想解释以下几点:
·当客户端运行时,它开通一个套接字并通过发送 HELO RFC给服务器与ChatServer 建立连接。一旦连接上,客户端将一直保持该套接字的连接和与服务器的通信,无论用户在什么时候发送命令。
·关于用户接口的设计。我建立了定制的Tab组件和Image支持的消息画布。
·创建消息画布的基本逻辑较简单些:无论用户什么时候输入消息,我都把该消息存储到一个数组列表中。而且,在这个列表中,我保留了每条消息的X和Y的偏移位置。详见下面的源码解释:
//Ex:
...........
for(int i =0; i messagearraylist.size();i++)
{
PaintMessageToMessageCanvas((MessageObject)messagearraylist.get(i);
}.........
/**************************************************************
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)下面函数用来绘制图像和文本消息
**************************************************************/
private void PaintMessageIntoCanvas(MessageObject messageObject)
{
int m_YPos = messageobject.StartY - YOffset;
int m_XPos = 5 - XOffset;
int CustomWidth = 0;
String Message = messageobject.Message;
/*************以用户名字体打印出用户名 **************/
if(Message.indexOf(":") = 0)
{
graphics.setFont(UserNameFont);
chatclient.getGraphics().setFont(UserNameFont);
fontmetrics = chatclient.getGraphics().getFontMetrics();
String m_UserName = Message.substring(0,Message.indexOf(":")+1);
graphics.drawString(m_UserName,m_XPos+CustomWidth,m_YPos);
CustomWidth+=fontmetrics.stringWidth(m_UserName)+HorizantalSpace;
Message = Message.substring(Message.indexOf(":")+1);
}
/*********设置文本的字体**********/
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)chatclient.getGraphics().setFont(TextFont);
graphics.setFont(TextFont);
fontmetrics = chatclient.getGraphics().getFontMetrics();
/**********打印图像区域********/
if(messageobject.IsImage == true)
{
tokenizer = new StringTokenizer(Message," ");
while(tokenizer.hasMoreTokens())
{
TokenString = tokenizer.nextToken();
if(TokenString.indexOf("~~") = 0)
{
/********如果是正确的图像*************/
try {
int m_ImageIndex = Integer.parseInt(TokenString.substring(2));
if((m_ImageIndex = 0) && (m_ImageIndex chatclient.IconCount))
{
graphics.drawImage(chatclient.IconArray[m_ImageIndex]
,m_XPos+CustomWidth,m_YPos - 15,messageobject.Width,messageobject.Height,this);
CustomWidth+=messageobject.Width+HorizantalSpace;
}
}
catch(Exception _Exc) { }
}
else
{
graphics.drawString(TokenString,m_XPos+CustomWidth,m_YPos);
CustomWidth+=fontmetrics.stringWidth(TokenString)+HorizantalSpace;
}
if(TotalWidth m_XPos+CustomWidth)
{
TotalWidth = m_XPos