界面聊天v1

该文详细描述了一个基于JavaSwing构建的聊天应用的界面设计和基本功能实现,包括创建聊天消息区域、输入框、发送按钮,设置字体和布局,以及好友和群组列表的显示和监听器。同时,文章还涵盖了服务端和客户端的简单模型,包括Socket通信和异常处理机制。
摘要由CSDN通过智能技术生成

目录

1、创建聊天消息的区域(不是发送消息的区域)

2、发送消息的区域

3、文本发送

        发送按钮

按钮监听器

4、建立主存储容器,存储以上容器

5、好友列表

列表中的内容

列表组件加入主组件中

以及设定显示好友列表的字体

监听器部分

6、群组列表

群组名字创建

字体

组件在主组件位置

 监听器

7、服务端

8、客户端

 消息发送方法


具体效果

 

1、创建聊天消息的区域(不是发送消息的区域)

        private JTextArea messageArea;//多行纯文本区域


        messageArea = new JTextArea();//对象构建
    
/*
   消息接收发送区域
 */
        JPanel messagePanel = new JPanel(new BorderLayout());//缓冲区 BorderLayout边界布局容器
        messageArea.setFont(new Font("微软雅黑", Font.ITALIC,20));//设置输入字体大小
        messagePanel.add(new JScrollPane(messageArea),BorderLayout.CENTER);//JScrollPane轻量的可滚动视图 设置在组件中间
        

2、发送消息的区域

        private JTextField messageFile;//消息发送区域


        messageFile = new JTextField();//添加发送消息区域

    /*
发送消息区域
 */
        messageFile.setFont(new Font("微软雅黑" ,Font.PLAIN,12));//在此处设定字体并不能在输入的框内看见设定的效果
        messagePanel.add(new JScrollPane(messageFile),BorderLayout.SOUTH);//设置在组件下方(南方)

3、文本发送

  • 发送按钮

private JButton sendButton;//发送消息按钮



 sendButton = new JButton("发送");//消息发送按钮

/*
    添加按钮组件
*/
    
    JPanel buttonPanel = new JPanel(new FlowLayout());//FlowLayout 组件管理器
 
       buttonPanel.add(sendButton);
  • 按钮监听器

     sendButton.addActionListener(new ActionListener() {
               
             @Override
                
            public void actionPerformed(ActionEvent e) {
                 
             String message = messageFile.getText();
    
                
             messageArea.append("\n" + "Me: " + message );
                
             messageFile.setText("");
    
             
           for (Client client: clients) {
             
               client.sendMessage(message);//遍历 并加入写好的类进行信息处理
              
          }
             
       }
         
     });

4、建立主存储容器,存储以上容器

    /*
        主界面组件控制分支组件显示
     */
        JPanel mainPanel = new JPanel(new BorderLayout());//BorderLayout 边界布局器
        
        mainPanel.add(messagePanel, BorderLayout.CENTER);//聊天消息区域添加到主组件中央
        
        mainPanel.add(buttonPanel,BorderLayout.SOUTH);//发送按钮设定到主组件的下方
        
        add(mainPanel);

值得一提的是:

        add(mainPanel);这行代码把主界面的东西加入到哪里了呢

        因为在写窗口类的过程中,主类是继承JFrame类,所以本类是具备JFrame中的特点的,最后把主界面的组件加入到的是本类对象当中。 

5、好友列表

  •        列表中的内容

    private JList<String> friendList;//好友列表
    
    /*
        写入好友列表的名字 静态
     */
     
       friendList = new JList<>(new String[]{"friend one"
                ,"friend two"
                ,"friend three"
        });

 

  • 列表组件加入主组件中

  • 以及设定显示好友列表的字体

/*
    设定显示好友图像的字体
    
    添加组件到主组件内
         
*/
        friendList.setFont(new Font("微软雅黑",Font.PLAIN,20));
        
        JScrollPane friendScroll = new JScrollPane(friendList);
        
        friendScroll.setPreferredSize(new Dimension(150,0));
        
        //设置 friendScroll 组件的首选大小 new Dimension(100,0) 表示组件期望的宽度和高度 100像素 0表时高度没确定
        
        mainPanel.add(friendScroll,BorderLayout.WEST);//把组件设置在西方

  • 监听器部分

    friendList.addListSelectionListener(new ListSelectionListener() {
            
        @Override
            
        public void valueChanged(ListSelectionEvent e) {
                
                System.out.println(e.getValueIsAdjusting());

                if (!e.getValueIsAdjusting()) {
                    String selectValue = friendList.getSelectedValue();
                    chatName = selectValue;
                    System.out.println(selectValue);

                    //设置窗体的标题
                    setTitle("Chat With: " + selectValue);

                    messageArea.setText("------" + selectValue + "-------");

                    setVisible(true);
                }
            }
        });

 

6、群组列表

  • 群组名字创建

 

        groupList = new JList<>(new String[]{
                    "group one",
                    "group two",
                    "group three"
        });
  • 字体

  • 组件在主组件位置

        groupList.setFont(new Font("微软雅黑",Font.PLAIN,20));
        

        JScrollPane groupJScroll = new JScrollPane(groupList);//把群组组件添加到上下可移动组件中
        

        groupJScroll.setPreferredSize(new Dimension(150,0));
        

        mainPanel.add(groupJScroll,BorderLayout.EAST);//添加到主组件东方
  •  监听器

    groupList.addListSelectionListener(new ListSelectionListener() {
           
         @Override
            
        public void valueChanged(ListSelectionEvent e) {
                
                System.out.println(e.getValueIsAdjusting());
                
                if (!e.getValueIsAdjusting()){
                    
                String selectValue = groupList.getSelectedValue();
                    
                    System.out.println(selectValue);

                    
                    //创建消息区域
                    
                    setTitle("Chat With:" +selectValue);
                    
                    chatName  = selectValue;
                    
                    messageArea.setText("--------" + selectValue +"-------");
                    
                    setVisible(true);
                }

            }
        });

 

7、服务端

private class ServerSocketTask implements Runnable{

        //内部类

        @Override
        public void run() {
            
        try {
                ServerSocket serverSocket = new ServerSocket(789);
                
        while(true){
                    
       /*
                    
            创建服务端和客户端对象
                     
        */
                   
                 Socket socket = serverSocket.accept();//while持续监听
                    
                 Client client = new Client(socket);
                    
                 clients.add(client);//放入创建的客户端存储容器种
                    
                 Thread clientThread = new Thread(client);//客户端加入线程
                    
                 clientThread.start();//启动线程
                
   }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

8、客户端

private class Client implements Runnable{

        private Socket socket;//创建客户端套接字
        
private String name;

        public Client(Socket socket) {
            
this.socket = socket;
            
this.name = socket.getRemoteSocketAddress().toString();
            
//将当前对象(即该类的一个实例)的name属性设置为客户端(socket)
            
// 的远程 IP 地址和端口号,以字符串的形式表示。
        
}

        
@Override
        
public void run() {
            
    while (true){
                
        try {
                    
            byte[] bytes = new byte[1024];//设定一个1024bit的存储空间 1KB
                    
            int len = socket.getInputStream().read(bytes);
                    
            //把客户端的输入的内容读取到byte里,并返回实际读取的字节数
                    
                String msg =  new String(bytes,0,len);

                messageArea.append("\n" + name + ": " + msg);

                } catch (IOException e) {
                    
                clients.remove(this);//删除当前连接客户端
                    
                //将当前对象(即该类的一个实例)
                    
                // 从存储客户端连接信息的容器中删除。
                    
                try {
                        
                socket.close();//关闭客户端
                       
                    } catch (IOException ioException) {
                        
                        ioException.printStackTrace();
                    
                    }
                    
                    e.printStackTrace();
                
                }
            
            }
        
}

有一个有趣的问题:为什么要在客户端出现异常的情况下把当前客户端关闭呢?这里会出现什么问题呢?

        会出现以下问题

  1. 资源泄露:如果是在输入输出流上出现异常,在资源没有得到回收的情况下,会出现资源泄露的问题。
  2. 死锁:异常在I/O操作当中,可能会造成死锁,而线程会等待I/O完成,而I/O可能会阻塞,导致没法退出,一直等待,导致死锁出现。
  3. 资源争夺:在不断开客户端的情况下,服务端会在异常的客户端上一直工作,会占用资源,从而影响服务器性能
  •  消息发送方法

       public void sendMessage(String message){
            
        try {
              
         socket.getOutputStream().write(message.getBytes());

//                将 message 内容转换成字节数组,然后通过 socket 的客户端输出流发送到服务端。
 
             socket.getOutputStream().flush();//刷新管道
            
} catch (IOException e) {
                
    e.printStackTrace();
            
}
       
}

 

源码链接🔗:

链接:https://pan.baidu.com/s/1puiRWIEVrJ7zf3OxMwjR3w 
提取码:fri0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值