使用java swing和socket编程实现简单的多人聊天室

来源:互联网 发布:淘宝评价怎么看五星 编辑:程序博客网 时间:2024/05/17 01:03

完成效果如下

客户端:


服务器端:


客户端功能:

输入服务器对应的端口,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 java.net.Socket;import java.net.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 = 7909370607161820239L;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<String> users = new ArrayList<String>();private String[] userstr;private int usersLength = 0;public ChatRoomClientFrame(){initServer();link.addActionListener(new ActionListener() {@Overridepublic 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 blocke1.printStackTrace();} catch (UnknownHostException e1) {e1.printStackTrace();} catch (IOException e1) {JOptionPane.showMessageDialog(null, "服务器未开启","错误",JOptionPane.ERROR_MESSAGE);e1.printStackTrace();} }}});discon.addActionListener(new ActionListener() {@Overridepublic 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 blocke1.printStackTrace();}}});send.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {send();}});message.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {send();}});font.addActionListener(new ActionListener() {@Overridepublic 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() {@Overridepublic 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 blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}});backGround.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Color bc = JColorChooser.showDialog(ChatRoomClientFrame.this, "选择颜色", Color.BLACK);chatRecords.setBackground(bc);}});foreGround.addActionListener(new ActionListener() {@Overridepublic 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{@Overridepublic 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<userstr.length-1;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 blocke1.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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void closing(){this.addWindowListener(new WindowAdapter() {@Overridepublic 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 blocke1.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 blocke1.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 java.net.BindException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.net.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<Socket> lists=new Vector<Socket>(); private ServerSocket serverSocket;private ServerThread st;private DataOutputStream dos;private DataInputStream dis;private ArrayList<String> users = new ArrayList<String>();private int usersLength = 0;private UserList ul;private String usermessage=null;private boolean isStart = false;public ChatRoomServerFrame(){initServer();start.addActionListener(new ActionListener() {@Overridepublic 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 blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}});stop.addActionListener(new ActionListener() {@Overridepublic 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 blocke1.printStackTrace();}}});send.addActionListener(new ActionListener() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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 blocke1.printStackTrace();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}});backGround.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {Color bc = JColorChooser.showDialog(ChatRoomServerFrame.this, "选择颜色", Color.BLACK);chatRecords.setBackground(bc);}});foreGround.addActionListener(new ActionListener() {@Overridepublic 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 blocke.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 blocke.printStackTrace();}}@Overridepublic 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<lists.size();i++){dos = new DataOutputStream(lists.get(i).getOutputStream());dos.writeUTF(str);} }catch (IOException e) {// TODO Auto-generated catch blocke.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<lists.size();i++){dos = new DataOutputStream(lists.get(i).getOutputStream());dos.writeUTF(str);} }catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}private class ServerThread extends Thread{private ServerSocket serverSocket;public ServerThread(ServerSocket serverSocket){this.serverSocket = serverSocket;}@Overridepublic 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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void closing(){this.addWindowListener(new WindowAdapter() {@Overridepublic 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 blocke1.printStackTrace();}}});}public class UserList extends Thread{@Overridepublic 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);              }          }      }  }







原创粉丝点击