【Betty】聊天室 —— 客户端
首先,本人来设计下 pojo层:
pojo层:
本人还是先来展示用于封装用户信息的pojo层对象:
用户信息的封装 —— UserInfo类:
package edu.youzg.chat_room.client.pojo;
public class UserInfo {
private String id;
private String nick;
private String password;
private String netId;
public UserInfo() {
}
public String getNetId() {
return netId;
}
public void setNetId(String netId) {
this.netId = netId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNick() {
return nick;
}
public void setNick(String nick) {
this.nick = nick;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserInfo other = (UserInfo) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
@Override
public String toString() {
return nick;
}
}
由于我们想要设计的 聊天室页面,有 好友列表
因此,在这里,还需要设计一个 好友列表池 —— FriendPool类:
好友列表池 —— FriendPool类:
package edu.youzg.chat_room.client.pojo;
import java.util.HashMap;
import java.util.Map;
public class FriendPool {
private Map<String, UserInfo> userPool;
public FriendPool() {
this.userPool = new HashMap<>();
}
public void addFriend(UserInfo user) {
userPool.put(user.getId(), user);
}
public void removeFriend(UserInfo user) {
userPool.remove(user.getId());
}
public UserInfo getUserById(String userId) {
return userPool.get(userId);
}
}
现在,我们来实现下 用于与服务器进行数据传输 的protocol层:
protocol层:
首先,是 组成App层通信协议 的 枚举 —— EAppCommand枚举:
App层通信协议 枚举 —— EAppCommand枚举:
package edu.youzg.chat_room.client.protocol;
public enum EAppCommand {
I_AM_COMMING,
I_AM_HERE,
I_AM_GONE,
TO_ONE,
TO_OTHER,
}
现在,本人再来编写 App层通信协议 的消息封装实体 —— ChatMessage类:
App层通信协议 的消息封装实体 —— ChatMessage类:
package edu.youzg.chat_room.client.protocol;
public class ChatMessage {
private EAppCommand command;
private String message;
public ChatMessage() {
}
public EAppCommand getCommand() {
return command;
}
public void setCommand(EAppCommand command) {
this.command = command;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
接下来,本人就来编写下客户端界面的view层:
view层:
首先是 客户端连接服务器的界面 —— ConnectToServerView 类:
连接服务器的界面 —— ConnectToServerView 类:
package edu.youzg.chat_room.client.view.connect;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.net.UnknownHostException;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import edu.youzg.betty.core.Client;
import edu.youzg.betty.core.ClientActionAdapter;
import edu.youzg.betty.exception.ClientActionNotSetException;
import edu.youzg.chat_room.client.view.login.LoginView;
import edu.youzg.util.ISwingHelper;
import edu.youzg.util.PromptBoxTool;
import edu.youzg.util.exceptions.FrameIsNullException;
public class ConnectToServerView implements ISwingHelper {
private JFrame jfrmConnectView;
private JLabel jlblMessage;
private int count;
private Client client;
public ConnectToServerView() {
this.count = 1;
}
public void initClient() throws UnknownHostException {
this.client = new Client();
this.client.initClient("/client.cfg.properties");
this.client.setClientAction(new ConnectAction());
}
@Override
public void init() {
jfrmConnectView = new JFrame("连接服务器");
jfrmConnectView.setLayout(new BorderLayout());
jfrmConnectView.setMinimumSize(new Dimension(300, 150));
jfrmConnectView.setLocationRelativeTo(null);
jfrmConnectView.setResizable(false);
jfrmConnectView.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
JLabel jlblTopic = new JLabel("连接服务器", 0);
jlblTopic.setFont(topicFont);
jlblTopic.setForeground(topicColor);
jfrmConnectView.add(jlblTopic, BorderLayout.NORTH);
jlblMessage = new JLabel("", 0);
jlblMessage.setFont(normalFont);
jfrmConnectView.add(jlblMessage);
}
public void startConnect() {
jlblMessage.setText("正在进行第" + count++ + "次连接……");
try {
while (!client.connectToServer()) {
int choice = PromptBoxTool.getChoice(jfrmConnectView, "连接服务器失败,是否继续尝试连接?",
JOptionPane.YES_NO_OPTION);
if (choice != JOptionPane.YES_OPTION) {
exitView();
return;
}
jlblMessage.setText("正在进行第" + count++ + "次连接……");
}
} catch (ClientActionNotSetException e) {
e.printStackTrace();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void reinit() {}
@Override
public void dealEvent() {
jfrmConnectView.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
try {
exitView();
} catch (FrameIsNullException e1) {
e1.printStackTrace();
}
}
});
}
@Override
public JFrame getFrame() {
return jfrmConnectView;
}
class ConnectAction extends ClientActionAdapter {
public ConnectAction() {
}
@Override
public void afterConnectToServer() {
// 连接成功,开始“登录”界面
LoginView loginView = new LoginView(client);
loginView.initView();
try {
loginView.showView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void serverAbnormalDrop() {
PromptBoxTool.showMessage(jfrmConnectView, "服务器拒绝连接,请稍后尝试……");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void serverOutOfRoom() {
PromptBoxTool.showMessage(jfrmConnectView, "服务器已满,请稍后尝试连接……");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
}
}
然后是用户登陆界面 —— LoginView 类:
用户登陆界面 —— LoginView 类:
package edu.youzg.chat_room.client.view.login;
import edu.youzg.betty.action.ActionBeanFactory;
import edu.youzg.betty.action.Actioner;
import edu.youzg.betty.action.Mapping;
import edu.youzg.betty.core.Client;
import edu.youzg.betty.core.ClientActionAdapter;
import edu.youzg.chat_room.client.pojo.UserInfo;
import edu.youzg.chat_room.client.view.chat.ChatRoomView;
import edu.youzg.util.ArgumentMaker;
import edu.youzg.util.ISwingHelper;
import edu.youzg.util.PromptBoxTool;
import edu.youzg.util.exceptions.FrameIsNullException;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
@Actioner
public class LoginView implements ISwingHelper {
private Client client;
private JFrame jfrmLogin;
private JLabel jlblRegistry;
private JButton jbtnLogin;
private JTextField jtxtUserName;
private JPasswordField jpswPassword;
public LoginView() {
}
public LoginView(Client client) {
this.client = client;
this.client.setClientAction(new LoginAction());
}
private void offline() {
client.offline();
}
@Override
public void dealEvent() {
jfrmLogin.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
offline();
}
});
jpswPassword.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
jpswPassword.setText("");
}
});
jtxtUserName.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
jtxtUserName.selectAll();
}
});
jtxtUserName.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jpswPassword.requestFocus();
}
});
jpswPassword.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jbtnLogin.requestFocus();
}
});
jbtnLogin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dealUserLogin();
}
});
jbtnLogin.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
dealUserLogin();
}
});
}
private void dealUserLogin() {
String id = jtxtUserName.getText();
String password = new String(jpswPassword.getPassword());
password = String.valueOf(password.hashCode());
ActionBeanFactory.setObject("afterLogin", this);
client.sendRequest("userLogin", "afterLogin", new ArgumentMaker()
.add("id", id)
.add("password", password)
.toString());
}
@Mapping("afterLogin")
public void afterLogin(UserInfo user) {
if (user.getId().equals("ERROR")) {
PromptBoxTool.showWarnning(jfrmLogin, "账号或密码错误!");
jpswPassword.setText("");
jtxtUserName.selectAll();
jtxtUserName.requestFocus();
return;
}
user.setNetId(client.getId());
client.sendMessageToServer("用户[" + user + "]进入聊天室!");
ChatRoomView chatRoomView = new ChatRoomView(client, user);
chatRoomView.initView();
try {
chatRoomView.showView();
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void init() {
jfrmLogin = new JFrame("用户登录");
jfrmLogin.setLayout(new BorderLayout());
jfrmLogin.setSize(300, 200);
jfrmLogin.setLocationRelativeTo(null);
jfrmLogin.setResizable(false);
jfrmLogin.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
JLabel jlblTopic = new JLabel("用户登录", 0);
jlblTopic.setFont(topicFont);
jlblTopic.setForeground(topicColor);
jfrmLogin.add(jlblTopic, BorderLayout.NORTH);
JPanel jpnlContxt = new JPanel();
jpnlContxt.setLayout(null);
jfrmLogin.add(jpnlContxt, BorderLayout.CENTER);
int normalSize = normalFont.getSize();
int left = 8*PADDING;
int top = 5*PADDING;
int lblWidth = 2 * normalSize;
int lblHeight = normalSize + 2;
JLabel jlblUserName = new JLabel("账号");
jlblUserName.setFont(normalFont);
jlblUserName.setBounds(left, top, lblWidth, lblHeight);
jpnlContxt.add(jlblUserName);
jtxtUserName = new JTextField();
jtxtUserName.setFont(normalFont);
jtxtUserName.setBounds(left + lblWidth + PADDING, top, 11*normalSize, lblHeight+4);
jpnlContxt.add(jtxtUserName);
top += lblHeight + 3*PADDING;
JLabel jlblPassword = new JLabel("密码");
jlblPassword.setFont(normalFont);
jlblPassword.setBounds(left, top, lblWidth, lblHeight);
jpnlContxt.add(jlblPassword);
jpswPassword = new JPasswordField();
jpswPassword.setFont(normalFont);
jpswPassword.setBounds(left + lblWidth + PADDING, top, 11*normalSize, lblHeight + 4);
jpnlContxt.add(jpswPassword);
JPanel jpnlButton = new JPanel();
jpnlButton.setLayout(new FlowLayout());
jfrmLogin.add(jpnlButton, BorderLayout.SOUTH);
jlblRegistry = new JLabel("注册");
jlblRegistry.setFont(new Font("微软雅黑", Font.BOLD, 16));
jlblRegistry.setForeground(new Color(5,98,44));
jlblRegistry.setCursor(handCursor);
jpnlButton.add(jlblRegistry);
JLabel jlblBlank = new JLabel(" ");
jlblBlank.setFont(normalFont);
jpnlButton.add(jlblBlank);
jbtnLogin = new JButton("登录");
jbtnLogin.setFont(smallFont);
jpnlButton.add(jbtnLogin);
}
@Override
public void reinit() {}
@Override
public JFrame getFrame() {
return jfrmLogin;
}
class LoginAction extends ClientActionAdapter {
public LoginAction() {
}
@Override
public boolean confirmOffline() {
int choice = PromptBoxTool.getChoice(jfrmLogin, "是否下线?", JOptionPane.YES_NO_OPTION);
return choice == JOptionPane.YES_OPTION;
}
@Override
public void afterOffline() {
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void serverAbnormalDrop() {
PromptBoxTool.showError(jfrmLogin, "服务器异常宕机,服务停止!");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void serverForcedown() {
PromptBoxTool.showMessage(jfrmLogin, "服务器强制宕机,服务停止!");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
}
}
最后是 客户端的聊天室界面 —— ChatRoomView 类:
聊天室界面 —— ChatRoomView 类:
package edu.youzg.chat_room.client.view.chat;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
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.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.google.gson.Gson;
import edu.youzg.betty.core.Client;
import edu.youzg.betty.core.ClientActionAdapter;
import edu.youzg.chat_room.client.pojo.FriendPool;
import edu.youzg.chat_room.client.pojo.UserInfo;
import edu.youzg.chat_room.client.protocol.ChatMessage;
import edu.youzg.chat_room.client.protocol.EAppCommand;
import edu.youzg.util.ArgumentMaker;
import edu.youzg.util.ISwingHelper;
import edu.youzg.util.PromptBoxTool;
import edu.youzg.util.exceptions.FrameIsNullException;
public class ChatRoomView implements ISwingHelper {
private Client client;
private JFrame jfrmChatRoomView;
private JTextArea jtatSystemMessage;
private JTextArea jtatChat;
private DefaultListModel<UserInfo> dlmFriendList;
private JList<UserInfo> jlstFriendList;
private JLabel jlblCurrentFriend;
private JTextField jtxtSpeakContext;
private JButton jbtnSend;
private UserInfo me;
private UserInfo all;
private FriendPool friendPool;
private Gson gson;
private static final String allId = "00000000";
public ChatRoomView(Client client, UserInfo me) {
this.gson = ArgumentMaker.gson;
this.friendPool = new FriendPool();
this.all = new UserInfo();
this.all.setId(allId);
this.all.setNick("所有人");
this.client = client;
this.client.setClientAction(new ChatRoomAction());
this.me = me;
}
@Override
public void reinit() {
dlmFriendList.addElement(all);
jlstFriendList.setSelectedIndex(0);
jlblCurrentFriend.setText(all.getNick());
// 向其他聊天室好友发送“我来了”的消息
Gson gson = ArgumentMaker.gson;
ChatMessage chatMessage = new ChatMessage();
chatMessage.setCommand(EAppCommand.I_AM_COMMING);
chatMessage.setMessage(gson.toJson(me));
client.toOther(gson.toJson(chatMessage));
}
private void showSystemMessage(String message) {
jtatSystemMessage.append(message + "\n");
jtatSystemMessage.setCaretPosition(jtatSystemMessage.getText().length());
}
private void showChatMessage(String message) {
jtatChat.append(message + "\n");
jtatChat.setCaretPosition(jtatChat.getText().length());
}
@Override
public void dealEvent() {
jfrmChatRoomView.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
client.offline();
}
});
jlstFriendList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == false) {
UserInfo curFriend = jlstFriendList.getSelectedValue();
if (curFriend == null) {
jlstFriendList.setSelectedIndex(0);
curFriend = jlstFriendList.getSelectedValue();
}
jlblCurrentFriend.setText(curFriend.toString());
}
}
});
jbtnSend.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String speakMessage = jtxtSpeakContext.getText();
jtxtSpeakContext.setText("");
if (speakMessage.length() <= 0) {
PromptBoxTool.showError(jfrmChatRoomView, "不能发送空消息!");
return;
}
UserInfo curFriend = jlstFriendList.getSelectedValue();
String orgNick = jlblCurrentFriend.getText();
if (!curFriend.getNick().equals(orgNick)) {
PromptBoxTool.showError(jfrmChatRoomView, "好友[" + orgNick + "]已经不在聊天室!");
return;
}
ChatMessage chatMessage = new ChatMessage();
String message = new ArgumentMaker()
.add("friend", me)
.add("message", speakMessage)
.toString();
if (curFriend.getId().equals(allId)) {
chatMessage.setCommand(EAppCommand.TO_OTHER);
chatMessage.setMessage(message);
client.toOther(gson.toJson(chatMessage));
showChatMessage("你对大家喊道:" + speakMessage);
} else {
chatMessage.setCommand(EAppCommand.TO_ONE);
chatMessage.setMessage(message);
client.toOne(curFriend.getNetId(), gson.toJson(chatMessage));
showChatMessage("你悄悄地对[" + curFriend + "]说道:" + speakMessage);
}
}
});
}
@Override
public JFrame getFrame() {
return jfrmChatRoomView;
}
class ChatRoomAction extends ClientActionAdapter {
public ChatRoomAction() {
}
@Override
public boolean confirmOffline() {
int choice = PromptBoxTool.getChoice(jfrmChatRoomView, "是否下线?", JOptionPane.YES_NO_OPTION);
return choice == JOptionPane.YES_OPTION;
}
@Override
public void beforeOffline() {
client.sendMessageToServer("用户[" + me + "]离开聊天室");
// 向其他好友发送“本尊下线”的消息
ChatMessage leaveMessage = new ChatMessage();
leaveMessage.setCommand(EAppCommand.I_AM_GONE);
leaveMessage.setMessage(gson.toJson(me));
client.toOther(gson.toJson(leaveMessage));
}
@Override
public void afterOffline() {
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void serverAbnormalDrop() {
PromptBoxTool.showError(jfrmChatRoomView, "服务器异常宕机,服务停止!");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
@Override
public void dealToOne(String sourceId, String message) {
ChatMessage chatMessage = gson.fromJson(message, ChatMessage.class);
EAppCommand command = chatMessage.getCommand();
String parameter = chatMessage.getMessage();
switch (command) {
case I_AM_HERE:
UserInfo friend = gson.fromJson(parameter, UserInfo.class);
friendPool.addFriend(friend);
dlmFriendList.addElement(friend);
break;
case TO_ONE:
ArgumentMaker argument = new ArgumentMaker(parameter);
UserInfo speaker = (UserInfo) argument.getValue("friend", UserInfo.class);
String speakContext = (String) argument.getValue("message", String.class);
showChatMessage("[" + speaker + "]对你悄悄地说:" + speakContext);
break;
default:
break;
}
}
@Override
public void dealToOther(String sourceId, String message) {
ChatMessage chatMessage = gson.fromJson(message, ChatMessage.class);
EAppCommand command = chatMessage.getCommand();
String parameter = chatMessage.getMessage();
switch (command) {
case I_AM_COMMING:
UserInfo newFriend = gson.fromJson(parameter, UserInfo.class);
friendPool.addFriend(newFriend);
dlmFriendList.addElement(newFriend);
showSystemMessage("好友[" + newFriend + "]进入聊天室");
ChatMessage echoMessage = new ChatMessage();
echoMessage.setCommand(EAppCommand.I_AM_HERE);
echoMessage.setMessage(gson.toJson(me));
client.toOne(sourceId, gson.toJson(echoMessage));
break;
case I_AM_GONE:
UserInfo leaveFriend = gson.fromJson(parameter, UserInfo.class);
friendPool.removeFriend(leaveFriend);
showSystemMessage("好友[" + leaveFriend + "]离开聊天室");
UserInfo curFriend = jlstFriendList.getSelectedValue();
dlmFriendList.removeElement(leaveFriend);
if (curFriend.equals(leaveFriend)) {
jlstFriendList.setSelectedIndex(0);
jlblCurrentFriend.setText(all.toString());
PromptBoxTool.showWarnning(jfrmChatRoomView, "好友[" + leaveFriend + "]已经离开");
}
break;
case TO_OTHER:
ArgumentMaker argument = new ArgumentMaker(parameter);
UserInfo speaker = (UserInfo) argument.getValue("friend", UserInfo.class);
String speakContext = (String) argument.getValue("message", String.class);
showChatMessage("[" + speaker + "]对大家喊道:" + speakContext);
break;
default:
break;
}
}
@Override
public void serverForcedown() {
PromptBoxTool.showMessage(jfrmChatRoomView, "服务器强制宕机,服务停止!");
try {
exitView();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
}
@Override
public void init() {
jfrmChatRoomView = new JFrame("右转哥粉丝聊天室");
jfrmChatRoomView.setDefaultCloseOperation(
JFrame.DO_NOTHING_ON_CLOSE);
jfrmChatRoomView.setSize(800, 600);
jfrmChatRoomView.setLocationRelativeTo(null);
Container container = jfrmChatRoomView.getContentPane();
container.setLayout(new BorderLayout());
JLabel jlblTopic = new JLabel("右粉聊天室", JLabel.CENTER);
jlblTopic.setFont(topicFont);
jlblTopic.setForeground(topicColor);
container.add(jlblTopic, BorderLayout.NORTH);
jtatSystemMessage = new JTextArea(0, 15);
jtatSystemMessage.setFont(normalFont);
JScrollPane jscpSystemMessage =
new JScrollPane(jtatSystemMessage);
jscpSystemMessage.setPreferredSize(new Dimension(200, 400));
TitledBorder ttdbSystemMessage = new TitledBorder(" 系统信息 ");
ttdbSystemMessage.setTitleFont(normalFont);
ttdbSystemMessage.setTitlePosition(TitledBorder.ABOVE_TOP);
ttdbSystemMessage.setTitleJustification(TitledBorder.CENTER);
jscpSystemMessage.setBorder(ttdbSystemMessage);
container.add(jscpSystemMessage, BorderLayout.EAST);
jtatChat = new JTextArea();
jtatChat.setFont(normalFont);
JScrollPane jscpChat = new JScrollPane(jtatChat);
TitledBorder ttdbChat = new TitledBorder(" 聊天信息 ");
ttdbChat.setTitleFont(normalFont);
ttdbChat.setTitleColor(Color.RED);
ttdbChat.setTitlePosition(TitledBorder.ABOVE_TOP);
ttdbChat.setTitleJustification(TitledBorder.CENTER);
jscpChat.setBorder(ttdbChat);
container.add(jscpChat, BorderLayout.CENTER);
JPanel jpnlFriends = new JPanel(new BorderLayout());
container.add(jpnlFriends, BorderLayout.WEST);
JPanel jpnlWelcome = new JPanel(new GridLayout(0, 1));
jpnlFriends.add(jpnlWelcome, BorderLayout.NORTH);
JLabel jlblWelcome = new JLabel(" 欢迎 ", JLabel.CENTER);
jlblWelcome.setFont(normalFont);
jlblWelcome.setForeground(Color.RED);
jpnlWelcome.add(jlblWelcome);
JLabel jlblUserSelf = new JLabel(me.getNick(), JLabel.CENTER);
jlblUserSelf.setFont(normalFont);
jlblUserSelf.setForeground(topicColor);
jpnlWelcome.add(jlblUserSelf);
dlmFriendList = new DefaultListModel<>();
jlstFriendList = new JList<>(dlmFriendList);
jlstFriendList.setFont(normalFont);
JScrollPane jscpFriendList =
new JScrollPane(jlstFriendList);
jscpFriendList.setPreferredSize(new Dimension(200, 300));
TitledBorder ttdbFriendList =
new TitledBorder(" 好友列表 ");
ttdbFriendList.setTitleFont(normalFont);
ttdbFriendList.setTitlePosition(TitledBorder.TOP);
ttdbFriendList.setTitleJustification(
TitledBorder.CENTER);
jscpFriendList.setBorder(ttdbFriendList);
jpnlFriends.add(jscpFriendList, BorderLayout.CENTER);
JPanel jpnlCurFriend =
new JPanel(new GridLayout(0, 1));
jpnlFriends.add(jpnlCurFriend, BorderLayout.SOUTH);
JLabel jlblCurrentFriendCaption =
new JLabel("当前好友", 0);
jlblCurrentFriendCaption.setFont(normalFont);
jpnlCurFriend.add(jlblCurrentFriendCaption);
jlblCurrentFriend = new JLabel("", JLabel.CENTER);
jlblCurrentFriend.setFont(normalFont);
jlblCurrentFriend.setForeground(Color.RED);
jpnlCurFriend.add(jlblCurrentFriend);
JPanel jpnlFooter = new JPanel();
container.add(jpnlFooter, BorderLayout.SOUTH);
JLabel jlblYousay = new JLabel("你说 ");
jlblYousay.setFont(normalFont);
jpnlFooter.add(jlblYousay);
jtxtSpeakContext = new JTextField(40);
jtxtSpeakContext.setFont(normalFont);
jpnlFooter.add(jtxtSpeakContext);
jbtnSend = new JButton("发送");
jbtnSend.setFont(smallFont);
jpnlFooter.add(jbtnSend);
}
}
最后,本人再来给出所需的配置文件:
配置文件
首先是 用于初始化客户端连接参数的 client.cfg.properties 文件
client.cfg.properties 文件:
ip=localhost
port=6666
启动层:
客户端启动类 —— ChatRoomClientMain类:
package edu.youzg.chat_room.client.Main;
import edu.youzg.betty.action.ActionBeanFactory;
import edu.youzg.chat_room.client.view.connect.ConnectToServerView;
import edu.youzg.util.exceptions.FrameIsNullException;
import java.net.UnknownHostException;
public class ChatRoomClientMain {
public static void main(String[] args) {
ActionBeanFactory.scanPackage("edu.youzg.chat_room.client.view");
try {
ConnectToServerView connectToServer = new ConnectToServerView();
connectToServer.initClient();
connectToServer.initView();
connectToServer.showView();
connectToServer.startConnect();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FrameIsNullException e) {
e.printStackTrace();
}
}
}
至于运行结果,本人将放在总集篇为同学们展示。
(本人 聊天室总集篇 博文 ——《【Betty】使用展示 —— 聊天室》链接:
https://www.cnblogs.com/codderYouzg/p/12749222.html)