//ChatClient.java
package chatclient;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.rmi.RemoteException;
import java.util.Hashtable;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.text.JTextComponent;
import javax.swing.text.Keymap;
import chat.ChatServer;
import chat.Chatter;
public class ChatClient extends JFrame {
//存储已有聊天用户,key:用户名.value: 对应的Chatter对象
Hashtable hash = new Hashtable();
//自己的用户名
String my_name = "chatter";
//服务器地址
String serverAddr;
//代表客户端到远程对象
Chatter chatter;
//服务器端到远程对象
ChatServer server;
JTextArea displayBox;
JTextArea inputBox;
JComboBox usersBox;
JButton sendButton;
JLabel statusLabel;
ConnectionAction connectAction = new ConnectionAction();
//让用户输入用户名和服务器地址到对话框
ConnectDlg dlg = new ConnectDlg(this);
public static void main(String[] args) {
new ChatClient();
}
//客户端界面类构造函数
public ChatClient() {
super("聊天-客户端");
layoutComponent();
setupMenu();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
exit();
}
});
show();
}
//设置菜单
private void setupMenu() {
JMenuBar menuBar = new JMenuBar();
JMenuItem conn = new JMenuItem(connectAction);
JMenuItem exit = new JMenuItem("退出");
exit.addActionListener(new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
exit();
}
});
JMenu file = new JMenu("文件");
file.add(conn);
menuBar.add(file);
setJMenuBar(menuBar);
}
//处理 退出 的函数
private void exit() {
destroy();
System.exit(0);
}
//布置各个界面元素
public void layoutComponent() {
setSize(400, 400);
JPanel contentPane = new JPanel();
//使用GridBagLayout对各控件布局
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
contentPane.setLayout(gridbag);
//最上端的显示消息的文本域
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 6;
c.weightx = 100;
c.weighty = 100;
c.insets.top = 5;
displayBox = new JTextArea();
displayBox.setLineWrap(true);
displayBox.setEditable(false);
displayBox.setMargin(new Insets(5, 5, 5, 5));
JScrollPane scrollPane = new JScrollPane(displayBox);
contentPane.add(scrollPane, c);
//消息 标签
c.gridheight = 1;
c.weightx = 0;
c.weighty = 0;
c.insets.top = 10;
JLabel msgLabel = new JLabel("消息:");
contentPane.add(msgLabel, c);
//消息输入文本框
c.gridheight = 6;
c.insets.top = 0;
c.gridwidth = GridBagConstraints.RELATIVE;
c.weightx = 100;
inputBox = new JTextArea();
addKeymapBindings();
inputBox.setLineWrap(true);
inputBox.setWrapStyleWord(true);
JScrollPane inputScrollPane = new JScrollPane(inputBox);
inputScrollPane.setPreferredSize(new Dimension(250, 50));
inputScrollPane.setMinimumSize(new Dimension(250, 50));
contentPane.add(inputScrollPane, c);
//发送消息 按钮
c.weightx = 0;
c.gridwidth = GridBagConstraints.REMAINDER;
sendButton =
new JButton(
new ImageIcon(getClass().getResource("images/send.gif")));
sendButton.setToolTipText("发送消息");
sendButton.setPreferredSize(new Dimension(50, 50));
sendButton.setMinimumSize(new Dimension(50, 50));
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
sendMessage();
}
});
contentPane.add(sendButton, c);
//发送给 标签
c.weightx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridheight = 1;
JLabel sendtoLabel = new JLabel("发送给:");
contentPane.add(sendtoLabel, c);
//用户 下拉列表框
usersBox = new JComboBox();
usersBox.setBackground(Color.WHITE);
usersBox.addItem("所有用户");
contentPane.add(usersBox, c);
//状态栏
JPanel statusPane = new JPanel(new GridLayout(1, 1));
statusLabel = new JLabel("未连接");
statusPane.add(statusLabel);
contentPane.add(statusPane, c);
setContentPane(contentPane);
//实例化ChatterImpl对象
try {
chatter = new ChatterImpl(this);
} catch (Exception e) {
e.printStackTrace();
return;
}
}
public void destroy() {
try {
disconnect();
} catch (java.rmi.RemoteException ex) {
ex.printStackTrace();
}
}
//执行连接操作
protected void connect()
throws
java.rmi.RemoteException,
java.net.MalformedURLException,
java.rmi.NotBoundException {
server =
(ChatServer) java.rmi.Naming.lookup(
"//" + serverAddr + "/ChatServer");
server.login(my_name, chatter);
}
//退出聊天室
protected void disconnect() throws java.rmi.RemoteException {
if (server != null)
server.logout(my_name);
}
//**********************************************************************
//以下四个函数是实现Chatter接口
public void receiveEnter(
String name,
Chatter chatter,
boolean hasEntered) {
if (name != null && chatter != null) {
hash.put(name, chatter);
if (!name.equals(my_name)) {
//对新加入聊天到用户,在displayBox给出提示
if (!hasEntered)
display(name + " 进入聊天室");
usersBox.addItem(name);
}
}
}
public void receiveExit(String name) {
if (name != null && chatter != null)
hash.remove(name);
for (int i = 0; i < usersBox.getItemCount(); i++) {
if (name.equals((String) usersBox.getItemAt(i))) {
usersBox.remove(i);
break;
}
}
display(name + " 离开聊天室");
}
public void receiveChat(String name, String message) {
display(name + ": " + message);
}
public void receiveWhisper(String name, String message) {
display(name + " 私聊: " + message);
}
//*********************************************************************
//在消息输入框中 处理键盘消息,Ctrl+Enter换行,Enter则发送消息
protected void addKeymapBindings() {
Keymap keymap =
JTextComponent.addKeymap("MyBindings", inputBox.getKeymap());
Action action = null;
KeyStroke key = null;
//用户在消息输入框中按回车发送消息
action = new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
sendMessage();
}
};
key = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
keymap.addActionForKeyStroke(key, action);
//Ctrl+Enter则实现换行
action = new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
inputBox.append("\n");
}
};
key = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Event.CTRL_MASK);
keymap.addActionForKeyStroke(key, action);
inputBox.setKeymap(keymap);
}
//在显示消息的文本域中显示消息
private void display(String s) {
if (!s.endsWith("\n")) {
displayBox.append(s + "\n");
} else {
displayBox.append(s);
}
int length = displayBox.getText().length() - 1;
displayBox.select(length, length);
}
//从消息框取得消息内容,发送消息函数
private void sendMessage() {
String message = inputBox.getText();
if (message != null && message.length() > 0) {
inputBox.setText(null);
inputBox.setCaretPosition(0);
display(my_name + ":" + message);
if (server != null) {
if ("�
评论1