本文詳細記錄一款純 AWT 實現的 Java 聊天軟件開發全過程,重點剖析如何利用 AWT 組件構建個性化界面。項目特色在於:零 Swing 依賴、自研 Tab 控件與圖像畫布、完整客戶端/服務端架構、支持表情圖片、私聊、自定義配色及語音邀請等功能。
| 命令 | 功能說明 |
|---|---|
| HELO | 初始化服務器連接 |
| QUIT | 用戶退出聊天室 |
| KICK | 踢出用戶/禁止參與 |
| CHRO | 切換聊天室 |
| MESS | 發送普通消息 |
| PRIV | 發送私聊消息 |
| ROCO | 獲取指定聊天室在線人數 |
| CALL | 邀請語音聊天(本文未實現) |
自定義 UserObject 類,封裝用戶名、Socket 連接、所在聊天室等完整客戶端信息,便於統一管理。
服務端監聽 1436 端口,每新增一個客戶連接即啟動獨立 ChatCommunication 線程處理該用戶的所有命令交互:
// ChatServer.java 主循環
while (true) {
Socket socket = serverSocket.accept();
ChatCommunication chat = new ChatCommunication(socket);
}
// ChatCommunication 構造器
ChatCommunication(Socket socket) {
personalSocket = socket;
dout = new DataOutputStream(personalSocket.getOutputStream());
// 啟動專門線程監聽客戶端命令...
}
完全基於 AWT 實現標籤頁切換與富文本消息畫布,支持文本與表情圖片混排。
採用「數組列表存儲消息對象 + 坐標偏移量記錄」策略,重繪時遍歷列表調用 PaintMessageToMessageCanvas():
private void PaintMessageIntoCanvas(MessageObject messageObject) {
int m_YPos = messageObject.StartY - YOffset;
int m_XPos = 5 - XOffset;
int customWidth = 0;
String message = messageObject.Message;
// 1. 繪製用戶名(特殊字體)
if (message.indexOf(":") >= 0) {
graphics.setFont(userNameFont);
String userName = message.substring(0, message.indexOf(":") + 1);
graphics.drawString(userName, m_XPos + customWidth, m_YPos);
customWidth += fontMetrics.stringWidth(userName) + horizontalSpace;
message = message.substring(message.indexOf(":") + 1);
}
// 2. 繪製正文文本與圖片混排
graphics.setFont(textFont);
if (messageObject.IsImage) {
StringTokenizer tokenizer = new StringTokenizer(message, " ");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
if (token.indexOf("~~") >= 0) { // 圖片標記格式:~~索引
try {
int imgIndex = Integer.parseInt(token.substring(2));
if (imgIndex >= 0 && imgIndex < chatClient.iconCount) {
graphics.drawImage(chatClient.iconArray[imgIndex],
m_XPos + customWidth, m_YPos - 15,
messageObject.Width, messageObject.Height, this);
customWidth += messageObject.Width + horizontalSpace;
}
} catch (Exception ignored) {}
} else { // 普通文本
graphics.drawString(token, m_XPos + customWidth, m_YPos);
customWidth += fontMetrics.stringWidth(token) + horizontalSpace;
}
}
}
// 更新總寬度用於滾動條計算...
}
此設計實現了輕量級的富文本渲染,無需依賴 Swing 的 JEditorPane 或第三方庫。
純 AWT 開發雖增加了自研組件的工作量,卻帶來極小的運行時體積與極高的可控性,適合資源受限環境或教學演示。完整源碼見文中鏈接。