📄 qq.java
字号:
/**
* 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 {
/**
* 主方法:启动登陆线程
*/
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() {
/*
* 设置登陆界面
*/
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("服务器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);
/*
* 监听退出按钮(匿名内部类)
*/
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);
/**
* 监听器,监听"登陆"Button的点击和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));
/*
* 连接服务器
*/
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();
}
/*
* 启动聊天线程
*/
Thread chat = new ChatThread(loginname.getText(),
s, in, out);
loginf.setVisible(false);
loginf.setEnabled(false);
chat.start();
} catch (IOException e1) {// 流操作异常
t.setText("通讯失败,请重试!");
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连接服务器异常
t.setText("连接服务器失败,请重试!");
}
}
}
}
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("错误:登陆名不能小于" + NAME_MIN + "字符");
return false;
}
if (name.length() > NAME_MAX) {
t.setText("错误:登陆名不能大于" + NAME_MAX + "字符");
return false;
}
if (name.indexOf(" ") > -1) {
t.setText("错误:登陆名不能包含空格");
return false;
}
for (int i = 0; i < FORBID_WORDS.length; i++) {
if (name.indexOf(FORBID_WORDS[i]) > -1) {
t.setText("错误:登陆名不能包含敏感信息");
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;// 上一条信息的发出时间
private static int total;// 在线人数统计
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() {
/*
* 设置聊天室窗口界面
*/
f = new JFrame();
f.setSize(600, 400);
f.setTitle(SOFTWARE + " - " + name + " 当前在线人数:" + ++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);
/**
* 监听关闭按钮
*/
class MyWindowListener implements WindowListener {
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
/*
* 向服务器发送退出信息
*/
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);
/**
* 接收服务器发送的信息
*/
class GetMsgThread extends Thread {
public void run() {
try {
String msg, name;
while (!s.isClosed()) {
/*
* 不断接受服务器信息,外层循环防止读到null跳出循环
*/
while (!s.isClosed() && (msg = in.readLine()) != null) {
msg = specialMsg(msg);// 系统信息处理
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 + " 悄悄地对你说: " + 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 + " 说: " + msg + "\n");// 在窗口显示信息
} else {
ta.append(msg + "\n");
}
ta.setCaretPosition(ta.getText().length());
}
}
} catch (Exception e) {
out.println(SYSTEM_MSG + USER_LOGOUT);// 当异常产生时向系统发出退出信息
} finally {
try {
s.close();
} catch (IOException e) {
}
}
}
}
GetMsgThread gt = new GetMsgThread();
gt.start();
/*
* 监听用户在窗口输入的信息(匿名内部类)
*/
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);
}
/**
* 处理系统信息
*/
private String specialMsg(String msg) {
if (msg.startsWith(SYSTEM_MSG)) {
msg = msg.replaceFirst(SYSTEM_MSG, "");
/*
* 当有人进入聊天室
*/
if (msg.startsWith(ADD_USER)) {
msg = msg.replaceFirst(ADD_USER, "");
cb.addItem(msg);
// users.put(msg, new ChatWindow(msg));
total++;
msg += " 进入聊天室";
}
/*
* 当有人离开聊天室
*/
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 += " 退出聊天室";
}
/*
* 登陆时获得的在线用户列表信息
*/
else if (msg.startsWith(EXIST_USERS)) {
msg = msg.replaceFirst(EXIST_USERS, "");
cb.addItem(msg);
// users.put(msg, new ChatWindow(msg));
total++;
msg += " 正在聊天室";
}
/*
* 即时显示在线人数
*/
f.setTitle(SOFTWARE + " - " + name + " 当前在线人数:" + total);
return msg;
}
return msg;
}
/**
* 检查信息是否允许发送,包括检查敏感词汇/空信息/刷屏
*/
private boolean isAllowed(String msg, String msgto) {
/*
* 过滤空信息
*/
if (msg.length() == 0)
return false;
String errmsg = null;
/*
* 过滤敏感词汇
*/
for (int i = 0; i < FORBID_WORDS.length; i++) {
if (msg.indexOf(FORBID_WORDS[i]) > -1) {
errmsg = "包含敏感信息,信息发送失败!\n";
break;
}
}
long timenow = (new Date()).getTime();// 获得当前时间信息
/*
* 防刷屏
*/
if (timenow - time < TIME_BETWEEN_MSG * 1000) {
errmsg = "发送信息的最短间隔为" + TIME_BETWEEN_MSG + "秒,请勿刷屏!\n";
}
if (errmsg == null) {
time = timenow;// 记录发送信息时间
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("我 说: " + msg + "\n");
else {
if (isRoomShow)
ta.append("我悄悄地对 " + name1 + " 说: " + 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;
}
/** 选择移动的物体 */
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));
}
/** 控制移动 */
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;
}
/** 显示移动物体的线程 */
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 {
/** 产生的动作 */
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -