

package Client;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.TargetDataLine;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.border.TitledBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import Pojo.UserInfo;
//聊天室客戶端
public class ChatClient extends JFrame{
private ChatClient chatClient = this;
private int screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
private int screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
//圖形界面
private JTextPane txtShow;
private JTextPane txtShowPri;
private JTextField txtMsg;
private JLabel infoName;
private JLabel infoIp;
private JButton send;
private JButton clear;
private JButton record_start;
private JButton record_stop_send;
private JPanel nPanel;
private JPanel sPanel;
private JScrollPane rScroll;
private JScrollPane lScroll;
private JSplitPane Split;
private JComboBox<String> comboBox;
private SimpleAttributeSet attrset;
private DefaultListModel<String> listModel;
private JList<String> userList;
private Socket socket;
private static PrintWriter writer; // 寫訊息
private static BufferedReader reader; // 讀訊息
private MessageThread messageThread = null;// 負責接收訊息的執行緒
private Map<String, UserInfo> onLineUsers = new HashMap<String, UserInfo>();// 所有在線用戶
private boolean isConnected = false;
private int port = 30000;
private String ip = "";
private String Userip = "";
private String name;
private String UserValue = "";
private int info_ip_ = 0;
public ChatClient(String userName,String ip) {
//設定視窗屬性
super(userName);
this.Userip = ip;
this.name = userName;
this.setVisible(true);
this.setResizable(false);
//用戶資訊界面
infoName = new JLabel(userName);
//訊息展示
txtShow = new JTextPane();
txtShow.setEditable(false);
txtShowPri = new JTextPane();
txtShowPri.setEditable(false);
//屬性集
attrset = new SimpleAttributeSet();
StyleConstants.setFontSize(attrset, 15);
//訊息框
txtMsg = new JTextField();
//按鈕
send = new JButton("發送");
clear = new JButton("清屏");
record_start = new JButton("私聊");
record_stop_send = new JButton("群聊");
comboBox = new JComboBox<>();
comboBox.addItem("ALL");
//串列
listModel = new DefaultListModel<>();
userList = new JList<>(listModel);
//n面板
nPanel = new JPanel();
nPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
JLabel infoNameTip = new JLabel("用戶名 : ");
TitledBorder infoTitle = new TitledBorder("用戶資訊");
infoNameTip.setForeground(Color.WHITE);
infoName.setForeground(Color.WHITE);
infoTitle.setTitleColor(Color.WHITE);
nPanel.add(infoNameTip);
nPanel.add(infoName);
nPanel.setBorder(infoTitle);
//中間面板
rScroll = new JScrollPane(txtShow);
TitledBorder txtTitle = new TitledBorder("訊息");
txtTitle.setTitleColor(Color.DARK_GRAY);
rScroll.setBorder(txtTitle);
lScroll = new JScrollPane(userList);
TitledBorder userTitle = new TitledBorder("在線用戶");
userTitle.setTitleColor(Color.DARK_GRAY);
lScroll.setBorder(userTitle);
//s面板
sPanel = new JPanel(new BorderLayout());
sPanel.setLayout(null);
txtMsg.setBounds(0,0,600,100);
txtMsg.setBackground(Color.GRAY);
send.setBounds(420, 110, 150, 35);
send.setForeground(Color.DARK_GRAY);
comboBox.setBounds(30, 110, 100, 35);
comboBox.setForeground(Color.DARK_GRAY);
clear.setBounds(160, 110, 100, 35);
clear.setForeground(Color.DARK_GRAY);
//record_start.setBounds(290, 110, 100, 35);
//record_start.setForeground(Color.DARK_GRAY);
//record_stop_send.setBounds(420, 110, 150, 35);
//record_stop_send.setForeground(Color.DARK_GRAY);
sPanel.add(txtMsg);
sPanel.add(send);
sPanel.add(comboBox);
sPanel.add(clear);
sPanel.add(record_start);
//sPanel.add(record_stop_send);
//分割線
Split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, lScroll, rScroll);
Split.setDividerLocation(150);
//視窗屬性
this.setLayout(null);
nPanel.setBounds(0,0,600,80);
nPanel.setBackground(Color.GRAY);
Split.setBounds(0, 90, 600, 500);
sPanel.setBounds(0,600,600,200);
//添加組件
this.add(nPanel);
this.add(Split);
this.add(sPanel);
this.setBounds(0, 0, 600, 800);
screenWidth = Toolkit.getDefaultToolkit().getScreenSize().width;
screenHeight = Toolkit.getDefaultToolkit().getScreenSize().height;
//大小
this.setLocation((screenWidth - chatClient.getWidth()) / 2, (screenHeight - chatClient.getHeight()) / 2);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//連接服務器
ConnectServer();
//系結事件
txtMsg.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ComboBoxValue();
}
});
//發送訊息
send.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ComboBoxValue();
}
});
//清屏
clear.addActionListener(new ClearListener(txtShow));
//關閉視窗
this.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
if (isConnected) {
try {
// 斷開連接
boolean flag = ConnectClose();
if (flag == false) {
throw new Exception("斷開連接發生例外!");
} else {
JOptionPane.showMessageDialog(chatClient, "成功斷開!");
txtMsg.setEnabled(false);
send.setEnabled(false);
}
} catch (Exception e4) {
JOptionPane.showMessageDialog(chatClient, "斷開連接服務器例外:" + e4.getMessage(), "錯誤",
JOptionPane.ERROR_MESSAGE);
}
} else if (!isConnected) {
ConnectServer();
txtMsg.setEnabled(true);
send.setEnabled(true);
}
}
});
comboBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent evt) {
try {
if (ItemEvent.SELECTED == evt.getStateChange()) {
// 這個判斷是選擇只會得到一個結果,如果沒有判斷,會得到兩個相同的值,從而獲取不到所要選中的值,,
String value = comboBox.getSelectedItem().toString();
System.out.println(value);
UserValue = value;
}
} catch (Exception e) {
System.out.println("GGGFFF");
}
}
});
}
// 發送資訊
public static void sendMessage(String message) {
writer.println(message);
writer.flush();
}
// 連接服務器
private void ConnectServer() {
try {
socket = new Socket(ip, port);// 根據埠號和服務器IP建立連接
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
infoIp = new JLabel(Userip);
infoIp.setForeground(Color.WHITE);
if (info_ip_ == 0) {
nPanel.add(infoIp);
JOptionPane.showMessageDialog(this, name + " 連接服務器成功!");
}
info_ip_++;
// 發送客戶端用戶名和IP地址
sendMessage(name + "@" + "IP" + "@" + Userip);
sendMessage(name + "@" + "ADD");
sendMessage(name + "@" + "USERLIST");
sendMessage(name + "@" + "Login"+"@"+ Userip);
// 開啟接受訊息執行緒
messageThread = new MessageThread(reader);
messageThread.start();
//設定服務器連接狀態
isConnected = true;
this.setVisible(true);
} catch (Exception e) {
isConnected = false;
JOptionPane.showMessageDialog(this, "連接服務器例外:" + e.getMessage(), "錯誤", JOptionPane.ERROR_MESSAGE);
}
}
// 斷開服務器連接
@SuppressWarnings("deprecation")//注解忽視警告
public synchronized boolean ConnectClose() {
try {
sendMessage(name + "@" + "DELETE");// 發送斷開連接命令
messageThread.stop();// 停止接受訊息執行緒
// 關閉連接
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
if (socket != null) {
socket.close();
}
isConnected = false;
return true;
} catch (IOException e) {
JOptionPane.showMessageDialog(this, name + " 斷開連接服務器失敗!");
isConnected = true;
return false;
}
}
//發送群聊、私聊資訊以及添加上線用戶資訊
public void ComboBoxValue() {
sendMessage(name + "@" + "USERLIST");
String message = txtMsg.getText();
if (message == null || message.equals("")) {
JOptionPane.showMessageDialog(this, "訊息不能為空!", "錯誤", JOptionPane.ERROR_MESSAGE);
return;
}
if (UserValue.equals("ALL")) {
sendMessage(this.getTitle() + "@" + "ALL" + "@" + message + "@" + "not");
} else {
sendMessage(this.getTitle() + "@" + comboBox.getSelectedItem().toString() + "@" + message + "@" + "not");
}
txtMsg.setText(null);
}
//接收訊息
class MessageThread extends Thread {
private BufferedReader reader;
// 構造方法
public MessageThread(BufferedReader reader) {
this.reader = reader;
}
public void run() {
String message = "";
while (true) {
try {
message = reader.readLine();
StringTokenizer stringTokenizer = new StringTokenizer(message, "/@");
// 分割字串轉化為陣列讀取服務器命令
String[] str_msg = new String[10];
int j = 0;
while (stringTokenizer.hasMoreTokens()) {
str_msg[j++] = stringTokenizer.nextToken();
}
String command = str_msg[1];// 信號
// 服務器已關閉信號
if (command.equals("SERVERClOSE")) {
Document docs = txtShow.getDocument();
try {
docs.insertString(docs.getLength(), "服務器已關閉!\\r\\n", attrset);// 對文本進行追加
} catch (BadLocationException e) {
e.printStackTrace();
}
// text_show.add("服務器已關閉!\r\n", null);
closeCon();// 關閉連接
return;// 結束執行緒
}
// 上線更新串列信號
else if (command.equals("Login")) {
String username = "";
String userIp = "";
username = str_msg[0];
userIp = str_msg[2];
UserInfo user = new UserInfo(username, userIp);
System.out.print("更新上線串列");
onLineUsers.put(username, user);
listModel.addElement(username);
comboBox.addItem(username);
}
// 下線更新串列信號
else if (command.equals("Logout")) {
String username = str_msg[0];
UserInfo user = (UserInfo) onLineUsers.get(username);
onLineUsers.remove(user);
listModel.removeElement(username);
comboBox.removeItem(username);
}
// 加載用戶串列
else if (command.equals("USERLIST")) {
String username = null;
String userIp = null;
for (int i = 2; i < str_msg.length; i += 2) {
if (str_msg[i] == null)
break;
username = str_msg[i];
userIp = str_msg[i + 1];
UserInfo user = new UserInfo(username, userIp);
onLineUsers.put(username, user);
if (listModel.contains(username))
;
else
listModel.addElement(username);
int len = comboBox.getItemCount();
int _i = 0;
for (; _i < len; _i++) {
if (comboBox.getItemAt(_i).toString().equals(username))
break;
}
if (_i == len)
comboBox.addItem(username);
else
;
}
}
// 人數已達上限信號
else if (command.equals("MAX")) {
closeCon();// 關閉連接
JOptionPane.showMessageDialog(chatClient, "服務器人數已滿,請稍后再試!", "提示", JOptionPane.CANCEL_OPTION);
return;// 結束執行緒
}
// 群發訊息
else if (command.equals("ALL")) {
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 設定日期格式
String time = df.format(new java.util.Date());
Document docs = txtShow.getDocument();
try {
docs.insertString(docs.getLength(),
"[" + time + "]\r\n" + str_msg[0] + " 說 : " + str_msg[2] + "\r\n\n", attrset);// 對文本進行追加
} catch (BadLocationException e) {
e.printStackTrace();
}
}
// 私聊訊息
else if (command.equals("ONLY")) {
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");// 設定日期格式
String time = df.format(new java.util.Date());
Document docs = txtShow.getDocument();
try {
docs.insertString(docs.getLength(), "[" + time + "]\r\n" + str_msg[0] + "\r\n\n",
attrset);// 對文本進行追加
} catch (BadLocationException e) {
e.printStackTrace();
}
}
str_msg = null; // 訊息陣列置空
}
catch (IOException e1) {
// ConnectServer();
e1.printStackTrace();
System.out.println("客戶端接受 訊息 執行緒 run() e1:" + e1.getMessage());
break;
} catch (Exception e2) {
// ConnectServer();
e2.printStackTrace();
System.out.println("客戶端接收 訊息 執行緒 run() e2:" + e2.getMessage());
break;
}
}
}
// 服務器停止后,客戶端關閉連接,
// synchronized用來修飾一個方法或者一個代碼塊的時候,能夠保證在同一時刻只有一個執行緒執行該段代碼,
public synchronized void closeCon() throws Exception {
listModel.removeAllElements();// 清空用戶串列
// 被動的關閉連接釋放資源
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
if (socket != null) {
socket.close();
}
isConnected = false;// 修改狀態為斷開
}
}
//清屏
public class ClearListener implements ActionListener{
private JTextPane txtShow;
public ClearListener(JTextPane txtShow) {
this.txtShow = txtShow;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
txtShow.setText("");
}
}
}
更多資訊關注微信公眾號:長長的路我們慢慢走吧
回復:Java考試系統
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/289255.html
標籤:其他
上一篇:基于SSM實作在線租房系統
