摘要:本文詳細介紹一個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);
}.........
/**************************************************************
下面函數用來繪制圖像和文本消息
**************************************************************/
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);
}
/*********設置文本的字體**********/
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