完成效果如下
客户端:
服务器端:
客户端功能:
输入服务器对应的端口,IP号,用户名(昵称),可以互相发送消息
服务器端功能:
输入端口号,启动,可以向所有客户端发送消息,IP地址自动获取。
下面是客户端界面:
package Test;
import UI.ChatRoomClientFrame;
public class ChatRoomClient {
public static void main(String[] args) {
new ChatRoomClientFrame().setVisible(true);
}
}客户端实现:
package UI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import .Socket;
import .UnknownHostException;
import java.util.Properties;
import javax.swing.JButton;
import javax.swing.JColorChooser;
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.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
public class ChatRoomClientFrame extends JFrame{
/**
*
*/
private static final long serialVersionUID = 790937060716189L;
private JPanel panel;
private JPanel northPanel;
private JPanel southPanel;
private JTextField port;
private JTextField IP;
private JTextField userName;
private JTextArea userlist;
private JTextArea chatRecords;
private JScrollPane leftPanel;
private JScrollPane rightPanel;
private JSplitPane centerPanel;
private JTextField message;
private JButton link;
private JButton discon;
private JButton send;
private JPanel Jpanel;
private JMenuBar bar;
private JMenu file;
private JMenuItem save;
private JMenu format;
private JMenuItem font;
private JMenuItem foreGround;
private JMenuItem backGround;
private Font myfont;
private boolean isConnect = false;
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos;
private ClientThread ct;
//private ArrayList users = new ArrayList();
private String[] userstr;
private int usersLength = 0;
public ChatRoomClientFrame(){
initServer();
link.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(userName.getText().trim().equals("")){
JOptionPane.showMessageDialog(null, "用户名不能为空","错误",JOptionPane.ERROR_MESSAGE);
}else{
try {
socket = new Socket(IP.getText(),Integer.parseInt(port.getText()));
dos = new DataOutputStream(socket.getOutputStream());
dis = new DataInputStream(socket.getInputStream());
if(socket!=null){
port.setEditable(false);
IP.setEditable(false);
userName.setEditable(false);
link.setEnabled(false);
discon.setEnabled(true);
ct = new ClientThread();
ct.start();
if(isConnect==false){
dos.writeUTF(userName.getText()+" 进入了聊天室");
isConnect=true;
}
}
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
JOptionPane.showMessageDialog(null, "服务器未开启","错误",JOptionPane.ERROR_MESSAGE);
e1.printStackTrace();
}
}
}
});
discon.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if(isConnect==true){
isConnect=false;
dos.writeUTF(userName.getText()+" 离开了聊天室");
userlist.setText("");
userstr=null;
usersLength=0;
dos.close();
dis.close();
socket.close();
chatRecords.append("n");
chatRecords.append("你离开了聊天室");
chatRecords.setCaretPosition(chatRecords.getDocument().getLength());
port.setEditable(true);
IP.setEditable(true);
userName.setEditable(true);
link.setEnabled(true);
discon.setEnabled(false);
ct.stop();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
send.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
send();
}
});
message.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
send();
}
});
font.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MyFontChooser mf = new MyFontChooser(chatRecords.getFont());
int returnValue = mf.showFontDialog(ChatRoomClientFrame.this);
// 如果按下的是确定按钮
if (returnValue == MyFontChooser.APPROVE_OPTION) {
// 获取选择的字体
Font font = mf.getSelectFont();
// 将字体设置到JTextArea中
chatRecords.setFont(font);
}
}
});
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FileDialog saveFile = new FileDialog(ChatRoomClientFrame.this, "保存文件...", FileDialog.SAVE);
saveFile.setVisible(true);
String filePath = saveFile.getDirectory() + saveFile.getFile();
try {
FileOutputStream fos = new FileOutputStream(filePath);
fos.write(chatRecords.getText().getBytes());
fos.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
backGround.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color bc = JColorChooser.showDialog(ChatRoomClientFrame.this, "选择颜色", Color.BLACK);
chatRecords.setBackground(bc);
}
});
foreGround.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color fc = JColorChooser.showDialog(ChatRoomClientFrame.this, "选择颜色", Color.BLACK);
chatRecords.setForeground(fc);
}
});
initFrame();
}
private void initServer() {
Jpanel = new JPanel();
Jpanel.setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new BorderLayout());
northPanel = new JPanel();
northPanel.setBorder(new TitledBorder("连接信息"));
bar = new JMenuBar();
file = new JMenu("记录");
save = new JMenuItem("保存");
format = new JMenu("格式");
font = new JMenuItem("字体");
foreGround = new JMenuItem("前景色");
backGround = new JMenuItem("背景色");
file.add(save);
format.add(font);
format.add(foreGround);
format.add(backGround);
bar.add(file);
bar.add(format);
Jpanel.add(bar,BorderLayout.NORTH);
port = new JTextField(8);
port.setText("8088");
IP = new JTextField(8);
IP.setText("192.168.24.8");
userName = new JTextField(8);
link= new JButton("启动");
discon= new JButton("停止");
discon.setEnabled(false);
northPanel.add(new JLabel("端口号"));
northPanel.add(port);
northPanel.add(new JLabel("服务器IP"));
northPanel.add(IP);
northPanel.add(new JLabel("用户名"));
northPanel.add(userName);
northPanel.add(link);
northPanel.add(discon);
panel.add(northPanel,BorderLayout.NORTH);
userlist = new JTextArea();
userlist.setLineWrap(true);
userlist.setEditable(false);
leftPanel =new JScrollPane(userlist);
leftPanel.setBorder(new TitledBorder("在线用户"));
panel.add(leftPanel,BorderLayout.EAST);
chatRecords = new JTextArea();
chatRecords.setLineWrap(true);
chatRecords.setEditable(false);
rightPanel =new JScrollPane(chatRecords);
rightPanel.setBorder(new TitledBorder("聊天信息"));
centerPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
centerPanel.setDividerLocation(100);
panel.add(centerPanel,BorderLayout.CENTER);
southPanel = new JPanel();
southPanel.setBorder(new TitledBorder("写消息"));
message = new JTextField(50);
send = new JButton("发送");
southPanel.add(message);
southPanel.add(send);
panel.add(southPanel, BorderLayout.SOUTH);
Jpanel.add(panel,BorderLayout.CENTER);
this.add(Jpanel);
}
private void initFrame(){
this.setTitle("聊天室-客户端");
this.setSize(640,480);
this.setLocationRelativeTo(null);
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.getImage("img/logo.jpg");
this.setIconImage(img);
this.setResizable(false);
opening();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
closing();
}
public class ClientThread extends Thread{
@Override
public void run() {
String message=null;
while(true){
try {
message = dis.readUTF();
if(message.contains("@在线用户列表@")){
userstr = message.split(" ");
if(userstr.length!=usersLength){
userlist.setText("");
for(int i=0;i
userlist.append(userstr[i]);
userlist.append("n");
}
usersLength = userstr.length;
}
}else{
chatRecords.append("n");
chatRecords.append(message);
chatRecords.setCaretPosition(chatRecords.getDocument().getLength());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
if(isConnect==true)
JOptionPane.showMessageDialog(null, "服务器断开连接","错误",JOptionPane.ERROR_MESSAGE);
link.setEnabled(true);
discon.setEnabled(false);
isConnect = false;
port.setEditable(true);
IP.setEditable(true);
userName.setEditable(true);
userlist.setText("");
userstr=null;
usersLength=0;
try {
dis.close();
dos.close();
socket.close();
ct.stop();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
}
public void send(){
if(isConnect==false){
JOptionPane.showMessageDialog(null, "未连接服务器,无法发送消息","错误",JOptionPane.ERROR_MESSAGE);
return;
}
if(message.getText().trim().equals("")){
JOptionPane.showMessageDialog(null, "消息不能为空","错误",JOptionPane.ERROR_MESSAGE);
return;
}
String str = message.getText();
sendMessage(str);
}
public void sendMessage(String str){
try {
dos.writeUTF(userName.getText()+": "+str);
} catch (IOException e) {
e.printStackTrace();
}
message.setText("");
}
public void opening(){
Properties p = new Properties();
try {
if(new File("src/FontClient.properties").exists()){
p.load(new FileReader("src/FontClient.properties"));
myfont = new Font(p.getProperty("FontName"),Integer.parseInt(p.getProperty("FontStyle")),Integer.parseInt(p.getProperty("FontSize")));
chatRecords.setFont(myfont);
chatRecords.setForeground(new Color(Integer.parseInt(p.getProperty("foreColor"))));
chatRecords.setBackground(new Color(Integer.parseInt(p.getProperty("backColor"))));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void closing(){
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if(isConnect == true){
try {
dos.writeUTF(userName.getText()+" 离开了聊天室");
dis.close();
dos.close();
socket.close();
ct.stop();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
Properties size = new Properties();
size.setProperty("FontName", ChatRoomClientFrame.this.chatRecords.getFont().getFamily());
size.setProperty("FontStyle", ChatRoomClientFrame.this.chatRecords.getFont().getStyle()+"");
size.setProperty("FontSize", ChatRoomClientFrame.this.chatRecords.getFont().getSize()+"");
size.setProperty("foreColor", ChatRoomClientFrame.this.chatRecords.getForeground().getRGB()+"");
size.setProperty("backColor", ChatRoomClientFrame.this.chatRecords.getBackground().getRGB()+"");
try {
FileWriter fr = new FileWriter("src/FontClient.properties");
size.store(fr, "FontClient Info");
fr.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
}服务器端界面:
package Test;
import UI.ChatRoomServerFrame;
public class ChatRoomServer {
public static void main(String[] args) {
new ChatRoomServerFrame().setVisible(true);
}
}服务器端实现:
package UI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import .BindException;
import .InetAddress;
import .ServerSocket;
import .Socket;
import .UnknownHostException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JColorChooser;
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.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
public class ChatRoomServerFrame extends JFrame{
/**
*
*/
private static final long serialVersionUID = -6582389471265865971L;
private JPanel panel;
private JPanel northPanel;
private JPanel southPanel;
private JTextField IP;
private JTextField port;
private JTextArea userlist;
private JTextArea chatRecords;
private JScrollPane leftPanel;
private JScrollPane rightPanel;
private JSplitPane centerPanel;
private JTextField message;
private JButton start;
private JButton stop;
private JButton send;
private JPanel Jpanel;
private JMenuBar bar;
private JMenu file;
private JMenuItem save;
private JMenu format;
private JMenuItem font;
private JMenuItem foreGround;
private JMenuItem backGround;
private Font myfont;
private Vector lists=new Vector();
private ServerSocket serverSocket;
private ServerThread st;
private DataOutputStream dos;
private DataInputStream dis;
private ArrayList users = new ArrayList();
private int usersLength = 0;
private UserList ul;
private String usermessage=null;
private boolean isStart = false;
public ChatRoomServerFrame(){
initServer();
start.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if(port.getText().trim().equals("")){
JOptionPane.showMessageDialog(null, "端口号不能为空","错误",JOptionPane.ERROR_MESSAGE);
return;
}
if(isStart==false){
serverSocket = new ServerSocket(Integer.parseInt(port.getText()));
chatRecords.append("n");
chatRecords.append("服务器已开启");
st = new ServerThread(serverSocket);
st.start();
port.setEditable(false);
start.setEnabled(false);
stop.setEnabled(true);
isStart = true;
ul = new UserList();
ul.start();
}
} catch (NumberFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
stop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
chatRecords.append("n");
chatRecords.append("服务器已断开");
chatRecords.setCaretPosition(chatRecords.getDocument().getLength());
if(dis != null){
dis.close();
}
if(dos != null){
dos.close();
}
users.removeAll(users);
userlist.setText("");
usersLength=0;
serverSocket.close();
port.setEditable(true);
start.setEnabled(true);
stop.setEnabled(false);
isStart = false;
ul.stop();
st.stop();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
send.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(lists.size()==0){
JOptionPane.showMessageDialog(null, "当前没有用户在线","错误",JOptionPane.ERROR_MESSAGE);
return;
}
if(message.getText().trim().equals("")){
JOptionPane.showMessageDialog(null, "消息不能为空","错误",JOptionPane.ERROR_MESSAGE);
return;
}
String line="服务器:"+message.getText();
sendMessage(line);
message.setText("");
}
});
message.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(lists.size()==0){
JOptionPane.showMessageDialog(null, "当前没有用户在线","错误",JOptionPane.ERROR_MESSAGE);
return;
}
if(message.getText().trim().equals("")){
JOptionPane.showMessageDialog(null, "消息不能为空","错误",JOptionPane.ERROR_MESSAGE);
return;
}
String line="服务器:"+message.getText();
sendMessage(line);
message.setText("");
}
});
font.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MyFontChooser mf = new MyFontChooser(chatRecords.getFont());
int returnValue = mf.showFontDialog(ChatRoomServerFrame.this);
// 如果按下的是确定按钮
if (returnValue == MyFontChooser.APPROVE_OPTION) {
// 获取选择的字体
Font font = mf.getSelectFont();
// 将字体设置到JTextArea中
chatRecords.setFont(font);
}
}
});
save.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
FileDialog saveFile = new FileDialog(ChatRoomServerFrame.this, "保存文件...", FileDialog.SAVE);
saveFile.setVisible(true);
String filePath = saveFile.getDirectory() + saveFile.getFile();
try {
FileOutputStream fos = new FileOutputStream(filePath);
fos.write(chatRecords.getText().getBytes());
fos.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
backGround.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color bc = JColorChooser.showDialog(ChatRoomServerFrame.this, "选择颜色", Color.BLACK);
chatRecords.setBackground(bc);
}
});
foreGround.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Color fc = JColorChooser.showDialog(ChatRoomServerFrame.this, "选择颜色", Color.BLACK);
chatRecords.setForeground(fc);
}
});
initFrame();
}
private void initServer() {
Jpanel = new JPanel();
Jpanel.setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new BorderLayout());
northPanel = new JPanel();
northPanel.setBorder(new TitledBorder("配置信息"));
IP = new JTextField(15);
String ipAddress = null;
try {
ipAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
IP.setText(ipAddress);
IP.setEditable(false);
port = new JTextField(15);
port.setText("8088");
start = new JButton("启动");
stop = new JButton("停止");
stop.setEnabled(false);
northPanel.add(new JLabel("本地地址"));
northPanel.add(IP);
northPanel.add(new JLabel("端口号"));
northPanel.add(port);
northPanel.add(start);
northPanel.add(stop);
bar = new JMenuBar();
file = new JMenu("记录");
save = new JMenuItem("保存");
format = new JMenu("格式");
font = new JMenuItem("字体");
foreGround = new JMenuItem("前景色");
backGround = new JMenuItem("背景色");
file.add(save);
format.add(font);
format.add(foreGround);
format.add(backGround);
bar.add(file);
bar.add(format);
Jpanel.add(bar,BorderLayout.NORTH);
panel.add(northPanel,BorderLayout.NORTH);
userlist = new JTextArea();
userlist.setEditable(false);
leftPanel =new JScrollPane(userlist);
leftPanel.setBorder(new TitledBorder("在线用户"));
panel.add(leftPanel,BorderLayout.EAST);
chatRecords = new JTextArea();
chatRecords.setEditable(false);
rightPanel =new JScrollPane(chatRecords);
rightPanel.setBorder(new TitledBorder("聊天信息"));
centerPanel = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
centerPanel.setDividerLocation(100);
panel.add(centerPanel,BorderLayout.CENTER);
southPanel = new JPanel();
southPanel.setBorder(new TitledBorder("写消息"));
message = new JTextField(50);
send = new JButton("发送");
southPanel.add(message);
southPanel.add(send);
panel.add(southPanel, BorderLayout.SOUTH);
Jpanel.add(panel, BorderLayout.CENTER);
this.add(Jpanel);
}
private void initFrame(){
this.setTitle("聊天室-服务器");
this.setSize(640,480);
this.setLocationRelativeTo(null);
Toolkit kit = Toolkit.getDefaultToolkit();
Image img = kit.getImage("img/logo.jpg");
this.setIconImage(img);
this.setResizable(false);
opening();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
closing();
}
private class MSThread implements Runnable{
private Socket socket;
private DataInputStream dis ;
public MSThread(Socket socket) {
try {
this.socket = socket;
dis = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
String message=null;
try {
while(true){
message = dis.readUTF();
if(message.contains("进入了聊天室")&&!message.contains(":"))
users.add(message.split(" ")[0]);
if(message.contains("离开了聊天室")&&!message.contains(":")){
users.remove(message.split(" ")[0]);
sendMessage(message);
dis.close();
socket.close();
lists.remove(socket);
}else{
sendMessage(message);
}
}
} catch (IOException e) {
lists.remove(socket);
e.printStackTrace();
}
}
}
public void sendMessage(String str){
try {
for(int i=0;i
dos = new DataOutputStream(lists.get(i).getOutputStream());
dos.writeUTF(str);
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(str);
chatRecords.append("n");
chatRecords.append(str);
chatRecords.setCaretPosition(chatRecords.getDocument().getLength());
}
public void sendUserMessage(String str){
try {
for(int i=0;i
dos = new DataOutputStream(lists.get(i).getOutputStream());
dos.writeUTF(str);
}
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private class ServerThread extends Thread{
private ServerSocket serverSocket;
public ServerThread(ServerSocket serverSocket){
this.serverSocket = serverSocket;
}
@Override
public void run() {
while(true)
{
Socket soket=null;
try {
soket=serverSocket.accept();
new Thread(new MSThread(soket)).start();
lists.add(soket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void opening(){
Properties p = new Properties();
try {
if(new File("src/FontServer.properties").exists()){
p.load(new FileReader("src/FontServer.properties"));
myfont = new Font(p.getProperty("FontName"),Integer.parseInt(p.getProperty("FontStyle")),Integer.parseInt(p.getProperty("FontSize")));
chatRecords.setFont(myfont);
chatRecords.setForeground(new Color(Integer.parseInt(p.getProperty("foreColor"))));
chatRecords.setBackground(new Color(Integer.parseInt(p.getProperty("backColor"))));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void closing(){
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
Properties size = new Properties();
size.setProperty("FontName", ChatRoomServerFrame.this.chatRecords.getFont().getFamily());
size.setProperty("FontStyle", ChatRoomServerFrame.this.chatRecords.getFont().getStyle()+"");
size.setProperty("FontSize", ChatRoomServerFrame.this.chatRecords.getFont().getSize()+"");
size.setProperty("foreColor", ChatRoomServerFrame.this.chatRecords.getForeground().getRGB()+"");
size.setProperty("backColor", ChatRoomServerFrame.this.chatRecords.getBackground().getRGB()+"");
try {
FileWriter fr = new FileWriter("src/FontServer.properties");
size.store(fr, "FontServer Info");
fr.close();
if(isStart == true){
if(dis != null){
dis.close();
}
if(dos != null){
dos.close();
}
serverSocket.close();
ul.stop();
st.stop();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
public class UserList extends Thread{
@Override
public void run() {
while(true){
if(users.size()!=usersLength){
userlist.setText("");
usermessage="";
for(String s : users){
userlist.append(s);
userlist.append("n");
usermessage=usermessage+s+" ";
}
usersLength = users.size();
sendUserMessage(usermessage+"@在线用户列表@");
}
}
}
}
}字体选择器:
package UI;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
public class MyFontChooser extends JDialog {
/**
*
*/
private static final long serialVersionUID = 7329415273324558584L;
/**
* 选择取消按钮的返回值
*/
public static final int CANCEL_OPTION = 0;
/**
* 选择确定按钮的返回值
*/
public static final int APPROVE_OPTION = 1;
/**
* 中文预览的字符串
*/
private static final String CHINA_STRING = "神马都是浮云!";
/**
* 英文预览的字符串
*/
private static final String ENGLISH_STRING = "Hello Kitty!";
/**
* 数字预览的字符串
*/
private static final String NUMBER_STRING = "0123456789";
// 预设字体,也是将来要返回的字体
private Font font = null;
// 字体选择器组件容器
private Box box = null;
// 字体文本框
private JTextField fontText = null;
// 样式文本框
private JTextField styleText = null;
// 文字大小文本框
private JTextField sizeText = null;
// 预览文本框
private JTextField previewText = null;
// 中文预览
private JRadioButton chinaButton = null;
// 英文预览
private JRadioButton englishButton = null;
// 数字预览
private JRadioButton numberButton = null;
// 字体选择框
private JList fontList = null;
// 样式选择器
private JList styleList = null;
// 文字大小选择器
private JList sizeList = null;
// 确定按钮
private JButton approveButton = null;
// 取消按钮
private JButton cancelButton = null;
// 所有字体
private String [] fontArray = null;
// 所有样式
private String [] styleArray = {"常规", "粗体", "斜体", "粗斜体"};
// 所有预设字体大小
private String [] sizeArray = {"8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "初号", "小初", "一号", "小一", "二号", "小二", "三号", "小三", "四号", "小四", "五号", "小五", "六号", "小六", "七号", "八号"};
// 上面数组中对应的字体大小
private int [] sizeIntArray = {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 42, 36, 26, 24, 22, 18, 16, 15, 14, 12, 10, 9, 8, 7, 6, 5};
// 返回的数值,默认取消
private int returnValue = CANCEL_OPTION;
/**
* 体构造一个字体选择器
*/
public MyFontChooser(Font font){
setTitle("字体选择器");
this.font = font;
// 初始化UI组件
init();
// 添加监听器
addListener();
// 按照预设字体显示
setup();
// 基本设置
setModal(true);
setResizable(false);
// 自适应大小
pack();
}
/**
* 初始化组件
*/
private void init(){
// 获得系统字体
GraphicsEnvironment eq = GraphicsEnvironment.getLocalGraphicsEnvironment();
fontArray = eq.getAvailableFontFamilyNames();
// 主容器
box = Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
fontText = new JTextField();
fontText.setEditable(false);
fontText.setBackground(Color.WHITE);
styleText = new JTextField();
styleText.setEditable(false);
styleText.setBackground(Color.WHITE);
sizeText = new JTextField("12");
// 给文字大小文本框使用的Document文档,制定了一些输入字符的规则
Document doc = new PlainDocument(){
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException {
if (str == null) {
return;
}
if (getLength() >= 3) {
return;
}
if (!str.matches("[0-9]+") && !str.equals("初号") && !str.equals("小初") && !str.equals("一号") && !str.equals("小一") && !str.equals("二号") && !str.equals("小二") && !str.equals("三号") && !str.equals("小三") && !str.equals("四号") && !str.equals("小四") && !str.equals("五号") && !str.equals("小五") && !str.equals("六号") && !str.equals("小六") && !str.equals("七号") && !str.equals("八号")) {
return;
}
super.insertString(offs, str, a);
sizeList.setSelectedValue(sizeText.getText(), true);
}
};
sizeText.setDocument(doc);
previewText = new JTextField(20);
previewText.setHorizontalAlignment(JTextField.CENTER);
previewText.setEditable(false);
previewText.setBackground(Color.WHITE);
chinaButton = new JRadioButton("中文预览", true);
englishButton = new JRadioButton("英文预览");
numberButton = new JRadioButton("数字预览");
ButtonGroup bg = new ButtonGroup();
bg.add(chinaButton);
bg.add(englishButton);
bg.add(numberButton);
fontList = new JList(fontArray);
styleList = new JList(styleArray);
sizeList = new JList(sizeArray);
approveButton = new JButton("确定");
cancelButton = new JButton("取消");
Box box1 = Box.createHorizontalBox();
JLabel l1 = new JLabel("字体:");
JLabel l2 = new JLabel("字形:");
JLabel l3 = new JLabel("大小:");
l1.setPreferredSize(new Dimension(165, 14));
l1.setMaximumSize(new Dimension(165, 14));
l1.setMinimumSize(new Dimension(165, 14));
l2.setPreferredSize(new Dimension(95, 14));
l2.setMaximumSize(new Dimension(95, 14));
l2.setMinimumSize(new Dimension(95, 14));
l3.setPreferredSize(new Dimension(80, 14));
l3.setMaximumSize(new Dimension(80, 14));
l3.setMinimumSize(new Dimension(80, 14));
box1.add(l1);
box1.add(l2);
box1.add(l3);
Box box2 = Box.createHorizontalBox();
fontText.setPreferredSize(new Dimension(160, 25));
fontText.setMaximumSize(new Dimension(160, 25));
fontText.setMinimumSize(new Dimension(160, 25));
box2.add(fontText);
box2.add(Box.createHorizontalStrut(5));
styleText.setPreferredSize(new Dimension(90, 25));
styleText.setMaximumSize(new Dimension(90, 25));
styleText.setMinimumSize(new Dimension(90, 25));
box2.add(styleText);
box2.add(Box.createHorizontalStrut(5));
sizeText.setPreferredSize(new Dimension(80, 25));
sizeText.setMaximumSize(new Dimension(80, 25));
sizeText.setMinimumSize(new Dimension(80, 25));
box2.add(sizeText);
Box box3 = Box.createHorizontalBox();
JScrollPane sp1 = new JScrollPane(fontList);
sp1.setPreferredSize(new Dimension(160, 100));
sp1.setMaximumSize(new Dimension(160, 100));
sp1.setMaximumSize(new Dimension(160, 100));
box3.add(sp1);
box3.add(Box.createHorizontalStrut(5));
JScrollPane sp2 = new JScrollPane(styleList);
sp2.setPreferredSize(new Dimension(90, 100));
sp2.setMaximumSize(new Dimension(90, 100));
sp2.setMinimumSize(new Dimension(90, 100));
box3.add(sp2);
box3.add(Box.createHorizontalStrut(5));
JScrollPane sp3 = new JScrollPane(sizeList);
sp3.setPreferredSize(new Dimension(80, 100));
sp3.setMaximumSize(new Dimension(80, 100));
sp3.setMinimumSize(new Dimension(80, 100));
box3.add(sp3);
Box box4 = Box.createHorizontalBox();
Box box5 = Box.createVerticalBox();
JPanel box6 = new JPanel(new BorderLayout());
box5.setBorder(BorderFactory.createTitledBorder("字符集"));
box6.setBorder(BorderFactory.createTitledBorder("示例"));
box5.add(chinaButton);
box5.add(englishButton);
box5.add(numberButton);
box5.setPreferredSize(new Dimension(90, 95));
box5.setMaximumSize(new Dimension(90, 95));
box5.setMinimumSize(new Dimension(90, 95));
box6.add(previewText);
box6.setPreferredSize(new Dimension(250, 95));
box6.setMaximumSize(new Dimension(250, 95));
box6.setMinimumSize(new Dimension(250, 95));
box4.add(box5);
box4.add(Box.createHorizontalStrut(4));
box4.add(box6);
Box box7 = Box.createHorizontalBox();
box7.add(Box.createHorizontalGlue());
box7.add(approveButton);
box7.add(Box.createHorizontalStrut(5));
box7.add(cancelButton);
box.add(box1);
box.add(box2);
box.add(box3);
box.add(Box.createVerticalStrut(5));
box.add(box4);
box.add(Box.createVerticalStrut(5));
box.add(box7);
getContentPane().add(box);
}
/**
* 按照预设字体显示
*/
private void setup() {
String fontName = font.getFamily();
int fontStyle = font.getStyle();
int fontSize = font.getSize();
/*
* 如果预设的文字大小在选择列表中,则通过选择该列表中的某项进行设值,否则直接将预设文字大小写入文本框
*/
boolean b = false;
for (int i = 0; i < sizeArray.length; i++) {
if (sizeArray[i].equals(String.valueOf(fontSize))) {
b = true;
break;
}
}
if(b){
// 选择文字大小列表中的某项
sizeList.setSelectedValue(String.valueOf(fontSize), true);
}else{
sizeText.setText(String.valueOf(fontSize));
}
// 选择字体列表中的某项
fontList.setSelectedValue(fontName, true);
// 选择样式列表中的某项
styleList.setSelectedIndex(fontStyle);
// 预览默认显示中文字符
chinaButton.doClick();
// 显示预览
setPreview();
}
/**
* 添加所需的事件监听器
*/
private void addListener() {
sizeText.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
setPreview();
}
public void focusGained(FocusEvent e) {
sizeText.selectAll();
}
});
// 字体列表发生选择事件的监听器
fontList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
fontText.setText(String.valueOf(fontList.getSelectedValue()));
// 设置预览
setPreview();
}
}
});
styleList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
styleText.setText(String.valueOf(styleList.getSelectedValue()));
// 设置预览
setPreview();
}
}
});
sizeList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
if(!sizeText.isFocusOwner()){
sizeText.setText(String.valueOf(sizeList.getSelectedValue()));
}
// 设置预览
setPreview();
}
}
});
// 编码监听器
EncodeAction ea = new EncodeAction();
chinaButton.addActionListener(ea);
englishButton.addActionListener(ea);
numberButton.addActionListener(ea);
// 确定按钮的事件监听
approveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 组合字体
font = groupFont();
// 设置返回值
returnValue = APPROVE_OPTION;
// 关闭窗口
disposeDialog();
}
});
// 取消按钮事件监听
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
disposeDialog();
}
});
}
/**
* 显示字体选择器
* @param owner 上层所有者
* @return 该整形返回值表示用户点击了字体选择器的确定按钮或取消按钮,参考本类常量字段APPROVE_OPTION和CANCEL_OPTION
*/
public final int showFontDialog(JFrame owner) {
setLocationRelativeTo(owner);
setVisible(true);
return returnValue;
}
/**
* 返回选择的字体对象
* @return 字体对象
*/
public final Font getSelectFont() {
return font;
}
/**
* 关闭窗口
*/
private void disposeDialog() {
MyFontChooser.this.removeAll();
MyFontChooser.this.dispose();
}
/**
* 显示错误消息
* @param errorMessage 错误消息
*/
private void showErrorDialog(String errorMessage) {
JOptionPane.showMessageDialog(this, errorMessage, "错误", JOptionPane.ERROR_MESSAGE);
}
/**
* 设置预览
*/
private void setPreview() {
Font f = groupFont();
previewText.setFont(f);
}
/**
* 按照选择组合字体
* @return 字体
*/
private Font groupFont() {
String fontName = fontText.getText();
int fontStyle = styleList.getSelectedIndex();
String sizeStr = sizeText.getText().trim();
// 如果没有输入
if(sizeStr.length() == 0) {
showErrorDialog("字体(大小)必须是有效“数值!");
return null;
}
int fontSize = 0;
// 通过循环对比文字大小输入是否在现有列表内
for (int i = 0; i < sizeArray.length; i++) {
if(sizeStr.equals(sizeArray[i])){
fontSize = sizeIntArray[i];
break;
}
}
// 没有在列表内
if (fontSize == 0) {
try{
fontSize = Integer.parseInt(sizeStr);
if(fontSize < 1){
showErrorDialog("字体(大小)必须是有效“数值”!");
return null;
}
}catch (NumberFormatException nfe) {
showErrorDialog("字体(大小)必须是有效“数值”!");
return null;
}
}
return new Font(fontName, fontStyle, fontSize);
}
/**
* 编码选择事件的监听动作
* @author 米强
*
*/
class EncodeAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(chinaButton)) {
previewText.setText(CHINA_STRING);
} else if (e.getSource().equals(englishButton)) {
previewText.setText(ENGLISH_STRING);
} else {
previewText.setText(NUMBER_STRING);
}
}
}
}