?? qq.java
字號(hào):
/**
* QQ聊天室客戶端
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.awt.geom.*;
public class Qq {
/**
* 主方法:啟動(dòng)登陸線程
*/
public static void main(String[] args) throws Exception {
Thread login = new LoginThread();
login.start();
}
}
/**
* 登陸線程
*/
class LoginThread extends Thread implements Protocol {
private JFrame loginf;
private JTextField t;
public void run() {
/*
* 設(shè)置登陸界面
*/
loginf = new JFrame();
loginf.setSize(400, 150);
loginf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginf.setTitle(SOFTWARE + " - 登陸");
t = new JTextField("Version " + VERSION + " By Lindan");
t.setHorizontalAlignment(JTextField.CENTER);
t.setEditable(false);
loginf.getContentPane().add(t, BorderLayout.SOUTH);
JPanel loginp = new JPanel(new GridLayout(3, 2));
loginf.getContentPane().add(loginp);
JTextField t1 = new JTextField("登陸名:");
t1.setHorizontalAlignment(JTextField.CENTER);
t1.setEditable(false);
loginp.add(t1);
final JTextField loginname = new JTextField("");
loginname.setHorizontalAlignment(JTextField.CENTER);
loginp.add(loginname);
JTextField t2 = new JTextField("服務(wù)器IP:");
t2.setHorizontalAlignment(JTextField.CENTER);
t2.setEditable(false);
loginp.add(t2);
final JTextField loginIP = new JTextField(DEFAULT_IP);
loginIP.setHorizontalAlignment(JTextField.CENTER);
loginp.add(loginIP);
/*
* 監(jiān)聽(tīng)退出按鈕(匿名內(nèi)部類)
*/
JButton b1 = new JButton("退 出");
loginp.add(b1);
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
final JButton b2 = new JButton("登 陸");
loginp.add(b2);
loginf.setVisible(true);
/**
* 監(jiān)聽(tīng)器,監(jiān)聽(tīng)"登陸"Button的點(diǎn)擊和TextField的回車
*/
class ButtonListener implements ActionListener {
private Socket s;
public void actionPerformed(ActionEvent e) {
if (checkName(loginname.getText())) {
try {
s = new Socket(loginIP.getText(), Integer
.parseInt(DEFAULT_PORT));
/*
* 連接服務(wù)器
*/
try {
InputStream is = s.getInputStream();
InputStreamReader ir = new InputStreamReader(is,
"GBK");
BufferedReader in = new BufferedReader(ir);
OutputStream os = s.getOutputStream();
OutputStreamWriter or = new OutputStreamWriter(os,
"GBK");
PrintWriter out = new PrintWriter(or);
out.println(VERSION);
out.flush();
out.println(loginname.getText());
out.flush();
String ver;
if (!(ver = in.readLine()).equals(VERSION)) {
throw new VersionException(ver);
}
if (in.readLine().equals(USER_EXIST)) {
throw new ExistException();
}
/*
* 啟動(dòng)聊天線程
*/
Thread chat = new ChatThread(loginname.getText(),
s, in, out);
loginf.setVisible(false);
loginf.setEnabled(false);
chat.start();
} catch (IOException e1) {// 流操作異常
t.setText("通訊失敗,請(qǐng)重試!");
try {
s.close();
} catch (IOException e2) {
}
} catch (VersionException e3) {// 用戶存在異常(接口中定義)
t.setText(e3.getMessage());
try {
s.close();
} catch (IOException e4) {
}
} catch (ExistException e5) {// 用戶存在異常(接口中定義)
t.setText(e5.getMessage());
try {
s.close();
} catch (IOException e6) {
}
}
} catch (IOException e7) {// Socket連接服務(wù)器異常
t.setText("連接服務(wù)器失敗,請(qǐng)重試!");
}
}
}
}
ButtonListener bl = new ButtonListener();
b2.addActionListener(bl);
loginname.addActionListener(bl);
loginIP.addActionListener(bl);
}
/**
* 判斷登陸名是否有效
*/
private boolean checkName(String name) {
if (name.length() < NAME_MIN) {
t.setText("錯(cuò)誤:登陸名不能小于" + NAME_MIN + "字符");
return false;
}
if (name.length() > NAME_MAX) {
t.setText("錯(cuò)誤:登陸名不能大于" + NAME_MAX + "字符");
return false;
}
if (name.indexOf(" ") > -1) {
t.setText("錯(cuò)誤:登陸名不能包含空格");
return false;
}
for (int i = 0; i < FORBID_WORDS.length; i++) {
if (name.indexOf(FORBID_WORDS[i]) > -1) {
t.setText("錯(cuò)誤:登陸名不能包含敏感信息");
return false;
}
}
return true;
}
}
/**
* 聊天線程
*/
class ChatThread extends Thread implements Protocol {
private Map users = new HashMap();
private String name;
private Socket s;
private BufferedReader in;
private PrintWriter out;
private JComboBox cb;
private JFrame f;
private JTextArea ta;
private JTextField tf;
private static long time;// 上一條信息的發(fā)出時(shí)間
private static int total;// 在線人數(shù)統(tǒng)計(jì)
public ChatThread(String name, Socket s, BufferedReader in, PrintWriter out) {
this.name = name;
this.s = s;
this.in = in;
this.out = out;
}
public static BounceFrame hyn = new BounceFrame();
public static BounceFrame hye = new BounceFrame();
public static BounceFrame hyw = new BounceFrame();
void runt() {
hyw.addBall();
hye.addBall();
hyn.addBall();
BounceFrame.counter++;
}
public void run() {
/*
* 設(shè)置聊天室窗口界面
*/
f = new JFrame();
f.setSize(600, 400);
f.setTitle(SOFTWARE + " - " + name + " 當(dāng)前在線人數(shù):" + ++total);
f.setLocation(300, 200);
ta = new JTextArea();
JScrollPane sp = new JScrollPane(ta);
ta.setEditable(false);
tf = new JTextField();
cb = new JComboBox();
cb.addItem("All");
JPanel pl = new JPanel(new BorderLayout());
pl.add(cb);
JPanel p = new JPanel(new BorderLayout());
p.add(pl, BorderLayout.WEST);
p.add(tf);
f.getContentPane().add(p, BorderLayout.SOUTH);
f.getContentPane().add(sp);
f.getContentPane().add(BounceFrame.canvas, BorderLayout.NORTH);
/**
* 監(jiān)聽(tīng)關(guān)閉按鈕
*/
class MyWindowListener implements WindowListener {
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
/*
* 向服務(wù)器發(fā)送退出信息
*/
out.println(SYSTEM_MSG + USER_LOGOUT);
out.flush();
try {
s.close();
} catch (IOException e1) {
}
System.exit(0);
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
}
MyWindowListener wl = new MyWindowListener();
f.addWindowListener(wl);
/**
* 接收服務(wù)器發(fā)送的信息
*/
class GetMsgThread extends Thread {
public void run() {
try {
String msg, name;
while (!s.isClosed()) {
/*
* 不斷接受服務(wù)器信息,外層循環(huán)防止讀到null跳出循環(huán)
*/
while (!s.isClosed() && (msg = in.readLine()) != null) {
msg = specialMsg(msg);// 系統(tǒng)信息處理
if (msg.startsWith(MSG_FROM)) {
msg = msg.replaceFirst(MSG_FROM, "");
name = msg.substring(0, msg.indexOf(NAME_END));
msg = msg.replaceFirst(name + NAME_END, "");
ta.append(name + " 悄悄地對(duì)你說(shuō): " + msg + "\n");
} else if (msg.contains(NAME_END)) {
name = msg.substring(0, msg.indexOf(NAME_END));
msg = msg.replaceFirst(name + NAME_END, "");
ta.append(name + " 說(shuō): " + msg + "\n");// 在窗口顯示信息
} else {
ta.append(msg + "\n");
}
ta.setCaretPosition(ta.getText().length());
}
}
} catch (Exception e) {
out.println(SYSTEM_MSG + USER_LOGOUT);// 當(dāng)異常產(chǎn)生時(shí)向系統(tǒng)發(fā)出退出信息
} finally {
try {
s.close();
} catch (IOException e) {
}
}
}
}
GetMsgThread gt = new GetMsgThread();
gt.start();
/*
* 監(jiān)聽(tīng)用戶在窗口輸入的信息(匿名內(nèi)部類)
*/
tf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String msg = e.getActionCommand();
if (isAllowed(msg, null)) {
sendMsg((String) cb.getSelectedItem(), msg, true);
tf.setText(null);
runt();
}
}
});
f.setVisible(true);
}
/**
* 處理系統(tǒng)信息
*/
private String specialMsg(String msg) {
if (msg.startsWith(SYSTEM_MSG)) {
msg = msg.replaceFirst(SYSTEM_MSG, "");
/*
* 當(dāng)有人進(jìn)入聊天室
*/
if (msg.startsWith(ADD_USER)) {
msg = msg.replaceFirst(ADD_USER, "");
cb.addItem(msg);
// users.put(msg, new ChatWindow(msg));
total++;
msg += " 進(jìn)入聊天室";
}
/*
* 當(dāng)有人離開(kāi)聊天室
*/
else if (msg.startsWith(DELETE_USER)) {
msg = msg.replaceFirst(DELETE_USER, "");
cb.removeItem(msg);
// ((ChatWindow) users.get(msg)).tas.append(msg + " 退出聊天室\n");
users.remove(msg);
total--;
msg += " 退出聊天室";
}
/*
* 登陸時(shí)獲得的在線用戶列表信息
*/
else if (msg.startsWith(EXIST_USERS)) {
msg = msg.replaceFirst(EXIST_USERS, "");
cb.addItem(msg);
// users.put(msg, new ChatWindow(msg));
total++;
msg += " 正在聊天室";
}
/*
* 即時(shí)顯示在線人數(shù)
*/
f.setTitle(SOFTWARE + " - " + name + " 當(dāng)前在線人數(shù):" + total);
return msg;
}
return msg;
}
/**
* 檢查信息是否允許發(fā)送,包括檢查敏感詞匯/空信息/刷屏
*/
private boolean isAllowed(String msg, String msgto) {
/*
* 過(guò)濾空信息
*/
if (msg.length() == 0)
return false;
String errmsg = null;
/*
* 過(guò)濾敏感詞匯
*/
for (int i = 0; i < FORBID_WORDS.length; i++) {
if (msg.indexOf(FORBID_WORDS[i]) > -1) {
errmsg = "包含敏感信息,信息發(fā)送失敗!\n";
break;
}
}
long timenow = (new Date()).getTime();// 獲得當(dāng)前時(shí)間信息
/*
* 防刷屏
*/
if (timenow - time < TIME_BETWEEN_MSG * 1000) {
errmsg = "發(fā)送信息的最短間隔為" + TIME_BETWEEN_MSG + "秒,請(qǐng)勿刷屏!\n";
}
if (errmsg == null) {
time = timenow;// 記錄發(fā)送信息時(shí)間
return true;
} else if (msgto == null)
ta.append(errmsg);
return false;
}
private void sendMsg(String name1, String msg, boolean isRoomShow) {
out.println(name1 + NAME_END + msg);
out.flush();
if (name1.equals("All"))
ta.append("我 說(shuō): " + msg + "\n");
else {
if (isRoomShow)
ta.append("我悄悄地對(duì) " + name1 + " 說(shuō): " + msg + "\n");
}
}
}
/** 顯示的物體 */
class Ball {
public int n = 0;
public Ball(Component c) {
canvas = c;
}
public Ball(Component c, Color color) {
canvas = c;
this.color = color;
}
/** 選擇移動(dòng)的物體 */
public void draw(Graphics2D g2) {
if (color != null)
g2.setColor(color);
int n = BounceFrame.counter % 4;
s = BounceFrame.counter % 3;
if (n == 0)
g2.drawString(ch[s], x + 8, y + 8);
if (n == 2)
g2.drawLine(x, y, x + 10, y + 10);
if (n == 3)
g2.fill3DRect(x, y, XSIZE, YSIZE, raised);
if (n == 1)
g2.fill(new Ellipse2D.Double(x, y, XSIZE, YSIZE));
}
/** 控制移動(dòng) */
public void move() {
if (x + XSIZE >= canvas.getWidth() && y + YSIZE >= canvas.getHeight()) {
y -= dy;
n = 1;
canvas.repaint();
return;
}
if (x + XSIZE >= canvas.getWidth() && y + YSIZE < canvas.getHeight()) {
if (n == 1) {
if (y == 12) {
x -= dx;
}
y -= dy;
}
canvas.repaint();
return;
}
if (x + XSIZE < canvas.getWidth() && y + YSIZE >= canvas.getHeight()) {
x += dx;
canvas.repaint();
return;
}
if (x + XSIZE < canvas.getWidth() && y + YSIZE < canvas.getHeight()) {
if (n == 0)
y += dy;
if (n == 1)
x -= dx;
canvas.repaint();
return;
}
}
private Component canvas;
private Color color;
private static final int XSIZE = 10;
private static final int YSIZE = 10;
private static final boolean raised = true;
private int x = 0;
private int y = 0;
private int dx = 2;
private int dy = 2;
String[] ch = { "郭", "志", "勇" };
public static int s = 2;
}
/** 顯示移動(dòng)物體的線程 */
class BallThread extends Thread {
public BallThread(Ball aBall) {
b = aBall;
}
public void run() {
try {
for (int i = 1; i <= 696; i++) {
b.move();
sleep(10);
}
} catch (InterruptedException iex) {
iex.printStackTrace();
}
}
private Ball b;
}
/** 生成2D圖行 */
class BallCanvas extends JPanel {
public void add(Ball b) {
balls.add(b);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
for (int i = 0; i < balls.size(); i++) {
Ball b = (Ball) balls.get(i);
b.draw(g2);
}
}
private ArrayList balls = new ArrayList();
}
/** 顯示窗口 */
class BounceFrame extends JPanel {
/** 產(chǎn)生的動(dòng)作 */
public void addBall() {
Ball b = new Ball(canvas, colors[counter % colors.length]);
canvas.add(b);
BallThread thread = new BallThread(b);
thread.start();
}
public static BallCanvas canvas = new BallCanvas();
public static final int WIDTH = 450;
public static final int HEIGHT = 350;
private Color[] colors = { Color.blue, Color.magenta, Color.green,
Color.orange, Color.red, Color.yellow, Color.pink };
public static int counter = 0;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -