2024年7月12日实训日志
学习内容
学习成果
// 初始化退出按钮 private void initExitButton() { exitButton = new JButton("退出"); exitButton.setBounds(260, 600, 100, 60); exitButton.setFont(Configuration.font); // 添加退出按钮的事件监听器(开始) exitButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { try { String messageToServer=Configuration.TYPE_EXIT + Configuration.SEPARATOR; outputStream.write(messageToServer.getBytes()); System.exit(0); // 退出虚拟机 } catch (Exception e) { } } }); // 添加退出按钮的事件监听器(结束) // 将控件添加至窗体 this.add(exitButton); } // 初始化在线好友列表 private void initOnlineJTable() { // 表格的列 String[] columnNames = { "IP", "端口" }; // 表格数据 Object[][] data = null; // 表格的数据模型 DefaultTableModel tableModel = new DefaultTableModel(data, columnNames) { // 设置表格不可编辑 @Override public boolean isCellEditable(int row, int column) { return false; } }; // 设置表格的数据模型 onlineJTable = new JTable(tableModel); onlineJTableJScrollPane = new JScrollPane(onlineJTable); // 设置滚动窗的水平滚动条属性:不出现 onlineJTableJScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); // 设置滚动窗的垂直滚动条属性:需要时自动出现 onlineJTableJScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); // 设置当前在线列表滚动窗大小和位置 onlineJTableJScrollPane.setBounds(420, 20, 250, 400); // 添加在线好友列表的鼠标事件监听器(开始) onlineJTable.addMouseListener(new MouseListener() { // 处理鼠标点击事件 @Override public void mouseClicked(MouseEvent event) { // 取得在线列表的数据模型 DefaultTableModel tableModel = (DefaultTableModel) onlineJTable.getModel(); // 提取鼠标选中的行作为消息目标(最少一个,最多为全体在线者) int[] selectedRows = onlineJTable.getSelectedRows(); //获取选中的行,所以是数组 // 将所有消息目标的cid拼接成一个字符串,以逗号分隔 chatTargetStringBuffer = new StringBuffer(); for (int i = 0; i < selectedRows.length; i++) { //遍历选中的列和行 int selectedRow = selectedRows[i]; String ip = (String) tableModel.getValueAt(selectedRow, 0); String port = (String) tableModel.getValueAt(selectedRow, 1); String cid = ip +":"+port; chatTargetStringBuffer.append(cid); if (i != selectedRows.length - 1) { chatTargetStringBuffer.append(","); } } tipLabel.setText("消息发送至:" + chatTargetStringBuffer); } @Override public void mousePressed(MouseEvent event) {}; @Override public void mouseReleased(MouseEvent event) {}; @Override public void mouseEntered(MouseEvent event) {}; @Override public void mouseExited(MouseEvent event) {}; }); // 添加在线好友列表的鼠标事件监听器(结束) // 将控件添加至窗体 this.add(onlineJTableJScrollPane); } // 设置窗体 public void setFrame(){ // 窗口关闭键无效,必须通过退出键退出客户端 //this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 获取屏幕的宽和高 int screenWidth = Utils.getScreenWidth(); int screenHeight = Utils.getScreenHeight(); // 计算窗体的显示位置 int x = (screenWidth - Configuration.CLIENT_FRAME_WIDTH) / 2; int y = (screenHeight - Configuration.CLIENT_FRAME_HEIGHT) / 2; this.setLocation(x, y); this.setVisible(true); } // 客户端连接服务器并发送上线消息 private void connectServer() { try { // 服务器地址和IP String ip = Utils.getIP(); int port = Configuration.SERVER_PORT; socket = new Socket(ip, port); // 获取输出流 outputStream = socket.getOutputStream(); // 组拼消息 String messageToServer=Configuration.TYPE_ONLINE + Configuration.SEPARATOR; // 向服务器发送上线消息 outputStream.write(messageToServer.getBytes()); } catch (Exception e) { System.out.println(e); } } // 客户端处理服务端发送来的消息 private void handleMessageFromServer() {//构造方法 try { while (true) { byte[] buf = new byte[1024 * 1];//设置字节数组 inputStream = socket.getInputStream();//获取从聊天框的消息 int len = inputStream.read(buf);//读取长度 // 处理服务器传来的消息 String messageFromServer = new String(buf, 0, len);//截取来自服务器的消息 System.out.println("客户端打印,客户端收到消息:"); System.out.println(messageFromServer); int separatorIndex=messageFromServer.indexOf(Configuration.SEPARATOR); //来自配置类的方法,indexOf数组下标 // (第一个斜杠之前的内容)消息类型:欢迎或者更新在线名单或者聊天 String messageType = messageFromServer.substring(0, separatorIndex); // (第一个斜杠之后的内容)消息内容:欢迎信息或者最新的在线名单或者聊天信息 String messageContent = messageFromServer.substring(separatorIndex + 1); // 欢迎信息 if (messageType.equals(Configuration.TYPE_WELCOME)) { //判断消息类型 // 显示欢迎信息 chatContentJTextArea.append(messageContent + Configuration.NEWLINE);//回车换行 // 将光标移动至控件底部 int length = chatContentJTextArea.getDocument().getLength();//不用看懂 chatContentJTextArea.setCaretPosition(length);//不用看懂 // 获取ip和端口并组拼为cid String[] lines = messageContent.split(Configuration.NEWLINE); // 取出最后一行 String lastLine = lines[lines.length - 1]; // 从最后一行来获取IP和端口 String[] ipPortParts = lastLine.split(", "); ip = ipPortParts[0].substring("客户端IP: ".length());//获取ip值 String portString = ipPortParts[1].substring("端口: ".length());//获取端口 port = Integer.valueOf(portString);//把端口号放在port中与IP:相连形成一段,命名为cid cid = ip+":"+port; } // 更新在线名单 if (messageType.equals(Configuration.TYPE_UPDATE)) { // 得到列表的数据模型 DefaultTableModel tableModel = (DefaultTableModel) onlineJTable.getModel(); //获取一个能够直接操作表格数据的对象 // 清空在线名单列表 tableModel.setRowCount(0); // 更新在线名单 String[] onlineArray = messageContent.split(","); // 添加当前在线好友 for (String online : onlineArray) { String[] stringArray = new String[2]; // 不添加自己本身 if (online.equals(cid)) { continue; } int colonIndex=online.indexOf(":"); stringArray[0] = online.substring(0, colonIndex); stringArray[1] = online.substring(colonIndex + 1); tableModel.addRow(stringArray); } // 提取在线列表的渲染模型 DefaultTableCellRenderer tableCellRenderer = new DefaultTableCellRenderer(); // 表格数据居中显示 tableCellRenderer.setHorizontalAlignment(JLabel.CENTER); // 设置表格渲染器 onlineJTable.setDefaultRenderer(Object.class, tableCellRenderer); } // 聊天 if (messageType.equals(Configuration.TYPE_CHAT)) { String[] stringArray = messageContent.split(Configuration.SEPARATOR); String from = stringArray[0]; String to = stringArray[1]; String content = stringArray[2]; chatContentJTextArea.append( Utils.getCurrentTime() + Configuration.NEWLINE + "来自" + from+ Configuration.NEWLINE + content + Configuration.NEWLINE); // 将光标移动至控件底部 int length = chatContentJTextArea.getDocument().getLength(); chatContentJTextArea.setCaretPosition(length); } } } catch (Exception e) { System.out.println(e); } } }
学习总结
今天除去新内容,我主要是在检查代码,找为什么我的窗口好友列表不会更新,我觉得问题应该就在列表更新那边,或者上线那边。但是找了很久还是没找到问题在哪。找到了一与些能运行的代码不同的地方,我用我的理解想着也觉得就是这个不同出的问题了,但是,就算改了我的代码还是不对。痛苦