仿QQ客户端

  • 当前效果
    • 登录界面
      • 好友列表界面

当前效果


登录界面

首先,为了达到美观的目的,需要添加一张背景图片,我采用的方法是将图片添加到JLabel上,再将JLabel添加到界面上,但这样会面临一个问题——界面上的其他组件会被遮挡(即使添加顺序在JLabel之后)寻找解决方法的过程中,我了解到JFrame有三层界面,分别是RootPane,LayeredPane,ContentPane。而我们可以将JLabel放置到中间层LayeredPane,并将ContentPane设置为透明(其他组件放置在ContentPane。除此之外,图片的大小一般与JLabel不同,这里将图片的尺寸修改为与JLabel尺寸相同。

        //修改图片尺寸Image image = new ImageIcon("登录背景.jpg").getImage().getScaledInstance(450, 330, JFrame.DO_NOTHING_ON_CLOSE);JLabel background = new JLabel(new ImageIcon(image));//将背景标签放置在中间层frame.getLayeredPane().add(background, Integer.valueOf(Integer.MIN_VALUE));//frame为JFrame类的一个对象JPanel panel = (JPanel) frame.getContentPane();//将最上层设置透明panel.setOpaque(false);

另一方面,原有的边框也不太美观,我选择直接将它除去,与此同时,需要添加两个按钮来控制窗体的最小化和关闭(在监听方法内操作)。为了使按钮不影响背景图片的美观,对按钮也要进行一系列的操作。首先需要处理两张去除背景的png图片,使其只有最小化和关闭的符号(用PS将多余的部分除去,导出为png)如图:

这是在照片里打开的样子,将它设置为按钮的图片时周围的格子是不可见的,可见的只有中间的符号。

然后将它们分别设置为按钮的图片。接着我们需要将按钮原本具有的背景隐藏,只保留刚刚设置的图片。最后将它们添加到右上角,而这设置位置的操作涉及到了布局,JFrame有BorderLayout,和FlowLayout等布局设置,但我们需要自定义位置,因此我们将JFrame的布局设置为null。组件可使用setBounds(x,y,width,height)方法设置位置和大小。

        JFrame frame = new JFrame();frame.setSize(450, 330);//设置不可改变大小frame.setResizable(false);//去边框frame.setUndecorated(true);frame.setLayout(null);JButton minimize = new JButton(new ImageIcon("最小化.png"));//将按钮设置透明minimize.setContentAreaFilled(false);//将按钮设置为无边框minimize.setBorderPainted(false);minimize.setBounds(390, 0, 30, 30);minimize.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {//最小化窗口frame.setExtendedState(1);}@Overridepublic void mouseEntered(MouseEvent e) {//鼠标移动到上面时使按钮呈现灰色minimize.setContentAreaFilled(true);minimize.setBackground(Color.GRAY);}@Overridepublic void mouseExited(MouseEvent e) {//鼠标移出时更改为原状态minimize.setContentAreaFilled(false);}});frame.add(minimize);JButton close = new JButton(new ImageIcon("关闭.png"));//将按钮设置透明close.setContentAreaFilled(false);//将按钮设置为无边框close.setBorderPainted(false);close.setBounds(420, 0, 30, 30);close.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {//关闭窗口System.exit(0);}@Overridepublic void mouseEntered(MouseEvent e) {//鼠标移动到上面时使按钮呈现红色close.setContentAreaFilled(true);close.setBackground(Color.RED);}@Overridepublic void mouseExited(MouseEvent e) {//鼠标移出时更改为原状态close.setContentAreaFilled(false);}});frame.add(close);

记住密码和自动登录使用JCheckBox实现。

        JCheckBox auto_sign_in = new JCheckBox("自动登录");auto_sign_in.setBounds(135, 200, 80, 20);//设置透明,使文本部分多余的部分不会遮挡背景auto_sign_in.setOpaque(false);frame.add(auto_sign_in);JCheckBox remember = new JCheckBox("记住密码");remember.setBounds(240, 200, 80, 20);remember.setOpaque(false);frame.add(remember);

其他组件的设置相对简单,在此不一一介绍了。

好友列表界面

首先,背景图片的设置和窗体布局等在前面介绍过,此处不再赘述,现在需要考虑的是如何实现好友列表。在这里采用选项卡组件和滚动面板加上JTree来实现,最主要的问题便是这些组件的透明设置和JTree的个性化设置(外观和点击节点进行的操作)由于要进行JTree的个性化设置,我们需要对JTree的节点DefaultMutableTreeNode进行一些更改,可创建一个类继承DefaultMutableTreeNode并添加自己所需的方法。同时,通过重写JTree的渲染器来实现更改外观的显示。

具体设置请参考以下代码:

public class PeopleNode extends DefaultMutableTreeNode {private String kind;// 好友分类private String account;// 好友账号private String name; // 好友昵称private String says; // 好友个性签名private int head; // 好友头像(不同的数字对应不同的图片)private boolean OnLineState = false;// 在线状态public PeopleNode(String kind, String account, String name, String says, int head) {super(name + says);//文本框放置昵称和个性签名this.kind = kind;this.account = account;this.name = name;this.says = says;this.head = head;}public String getKind() {return kind;}public String getAccount() {return account;}public String getName() {return name;}public String getSays() {return says;}public ImageIcon getImageIcon() {if (OnLineState) {return switch (head) {case 0 -> new ImageIcon("库里.jpg");case 1 -> new ImageIcon("克莱.png");default -> null;};} else {return switch (head) {case 0 -> getGrayImage(new ImageIcon("库里.jpg"));case 1 -> getGrayImage(new ImageIcon("克莱.png"));default -> null;};}}public boolean getOnLineState() {return OnLineState;}//图片灰度化处理public ImageIcon getGrayImage(ImageIcon icon){int w=icon.getIconWidth();int h=icon.getIconHeight();BufferedImage buff=new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);Graphics g=buff.getGraphics();g.drawImage(icon.getImage(),0,0,null);for (int i=0;i<w;i++){for(int j=0;j<h;j++){int red,green,blue;int pixel=buff.getRGB(i,j);red=(pixel>>16)&0xFF;green=(pixel>>8)&0xFF;blue=(pixel>>0)&0xFF;int sum=(red+green+blue)/3;g.setColor(new Color(sum,sum,sum));g.fillRect(i,j,1,1);}}return new ImageIcon(buff);}// 更改在线状态public void SetState(boolean OnLineState) {this.OnLineState = OnLineState;}}
        // 默认节点DefaultMutableTreeNode root = new DefaultMutableTreeNode();DefaultMutableTreeNode friend = new DefaultMutableTreeNode("我的好友");DefaultMutableTreeNode stranger = new DefaultMutableTreeNode("陌生人");DefaultMutableTreeNode blacklist = new DefaultMutableTreeNode("黑名单");// 以根节点创建树JTree contacts_tree = new JTree(root);// 设置为点击一次展开contacts_tree.setToggleClickCount(1);// 将节点添加到根节点root.add(friend);root.add(stranger);root.add(blacklist);/*** PeopleNode为继承了DefaultMutableTreeNode的类,people_list为存放PeopleNode的列表,* 在进行登录操作后从服务器获取的信息后动态生成*/for (int i = 0; i < people_list.size(); i++) {PeopleNode node = people_list.get(i);if (node.getKind().equals("我的好友")) {friend.add(node);}else if(node.getKind().equals("陌生人")){stranger.add(node);}else if(node.getKind().equals("黑名单")){blacklist.add(node);}}// 隐藏根节点contacts_tree.setRootVisible(false);// 展开树(在根节点隐藏时,能看见子节点)contacts_tree.expandPath(new TreePath(root));// 设置透明contacts_tree.setOpaque(false);// 隐藏根柄contacts_tree.setShowsRootHandles(false);// 对各个节点进行个性化设置contacts_tree.setCellRenderer(new DefaultTreeCellRenderer() {// 收起和展开图片设置为三角形final ImageIcon icon1 = new ImageIcon("收起.png");final ImageIcon icon2 = new ImageIcon("展开.png");// 重写该方法public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,boolean leaf, int row, boolean hasFocus) {super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);//节点为展开时显示的图片if (!expanded) {setIcon(icon1);} else {setIcon(icon2);}String str = value.toString();if (!str.equals("我的好友") && !str.equals("黑名单") && !str.equals("陌生人")) {DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;PeopleNode people = (PeopleNode) node;// 根据不同的好友对象设置他们的头像setIcon(new ImageIcon(people.getImageIcon().getImage().getScaledInstance(60, 60,JFrame.DO_NOTHING_ON_CLOSE)));// 将好友的昵称字体设置得比类别更小setFont(new Font("宋体", Font.BOLD, 15));} else {setFont(new Font("宋体", Font.BOLD, 20));}// 设置未选中节点时背景色为白色且完全透明,0表示透明,255表示正常setBackgroundNonSelectionColor(new Color(255, 255, 255, 0));// 设置选中节点时背景色为白色,透明度改为100,来区分未选中状态setBackgroundSelectionColor(new Color(255, 255, 255, 100));return this;}});// 使节点能响应相应操作contacts_tree.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {Object node = contacts_tree.getLastSelectedPathComponent();String str = node.toString();if (!str.equals("我的好友") && !str.equals("黑名单") && !str.equals("陌生人") && e.getClickCount() == 2) {//点击两次好友,弹出对话框}}});// 设置选项卡透明(需放置在创建之前)UIManager.put("TabbedPane.contentOpaque", false);// 创建选项卡JTabbedPane tab = new JTabbedPane();// 将创建并进行个性化设置的树添加到滚动面板JScrollPane jsp = new JScrollPane(contacts_tree);// 将滚动面板设置透明jsp.getViewport().setOpaque(false);jsp.setOpaque(false);jsp.setName("联系人");// 显示滚动条jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);// 最后将滚动面板添加到选项卡中tab.add(jsp);

以上只涉及到对界面的设置,具体的通信功能还未完善,进行登录操作和创建好友列表界面都需要与服务器进行交互,这部分功能未在以上的代码给出。

以上基本是我在写这部分界面代码时遇到的问题以及解决办法,遇到这些问题时,我找了好久才找到了这些解决方案,因此希望这篇博客可以帮助到有需要的朋友。

Java仿QQ客户端(用JTree实现好友列表)相关推荐

  1. java仿qq思路_java仿QQ聊天软件OIM艰辛之路(开源项目)

    既然QQ能仿ICQ, 咱java也来个仿QQ. 在我刚学完java后,就想做点什么项目锻炼下自己的技能.凑巧的是,我一个同样学java的朋友在做一个仿qq的项目,不过他做的实在太丑了. 然后他想让我也 ...

  2. 使用java导入某个msn帐号的好友列表并发送消息

    使用java导入某个msn帐号的好友列表并发送消息 导入信息的关键是如何对msn的通讯协议进行封装,这里会有两个选择,一个使用openfire(xmlapp协议),另外就是使用jml,前者配置起来相对 ...

  3. java仿qq好友列表_QQ好友列表树形列表java代码实现代码

    以前在网上瞎转悠的时候就发现很多人为用Java实现QQ登陆后的面板的问题感到十分头疼,最近我因在写模拟QQ的项目,故不可或缺的遇到了这一个问题,在网上我google了,百度了,最终发现的是有很多人被这 ...

  4. java仿qq好友列表_JTree实现QQ好友列表

    最近学习了一下JTree的使用方法: 先来看一下树的实例: 构建一个树, DefaultMutableTreeNode root = new DefaultMutableTreeNode(" ...

  5. Java仿QQ聊天系统Eclipse+MySql实现

    qq聊天项目使用简介: 通过之前的java学习,写了一个仿QQ的聊天程序,主要实现的功能有注册.登录.好友列表.发送文字.图片.文件.表情. 项目环境配置 软件开发工具:eclipse 项目结构:客户 ...

  6. java仿qq空间音乐播放_完美实现仿QQ空间评论回复特效

    评论回复是个很常见的东西,但是各大网站实现的方式却不尽相同.大体上有两种方式 1. 像优酷这种最常见,在输入框中@要回复的人,这种方式下,用www.cppcns.com户可以修改@. 新浪微博则是在这 ...

  7. java 仿qq空间_仿QQ空间和微信朋友圈,高解耦高复用高灵活

    先看看效果: 用极少的代码实现了 动态详情 及 二级评论 的 数据获取与处理 和 UI显示与交互,并且高解耦.高复用.高灵活. 动态列表界面MomentListFragment支持 下拉刷新与上拉加载 ...

  8. java仿QQ微信聊天室

    话不多说,先上图                                   即时通信系统:可以完成群聊.私人聊天,实时发送和显示聊天信息,完成好友列表,进一步可以带表情,附件发送,聊天信息的 ...

  9. java 仿qq mysql_基于Java远程通信(仿QQ)及应用研究设计(MySQL)(含录像)

    基于JAVA远程通信(仿QQ)及应用研究设计(MySQL)(含录像)(毕业论文13000字,程序代码,MySQL数据库) 随着信息社会脚步的日益加快,远程通信的应用正在人们的生产生活中扮演着极其重要的 ...

最新文章

  1. [CVPR 2020] RandLA-Net:大场景三维点云语义分割新框架(已开源)
  2. Solr添加SolrDocument报错
  3. elk,logstash -elastcisearch 429
  4. Cognos TM1_10.1.1服务端配置
  5. 将一个BYTE数组转换成16进制字符串和10进制字符串格式
  6. qt执行命令行失败_QT缺少 qtcore4.dll,debug下运行不成功
  7. Android 7.0系统启动流程分析
  8. 计算机网关,如何查看计算机的IP地址和网关
  9. 连载《一个程序猿的生命周期》-6、自学C++,二级考过后,为工作的机会打下了基础...
  10. Maven环境搭建和介绍
  11. 桌面版IDE将迎终结,Github发布代码空间Codespaces | 凌云时刻
  12. linux微软雅黑字体库_Debian系统中安装微软雅黑字体的教程
  13. wps excel日历_Excel处理日历
  14. clappr.js:Web开源媒体播放器,可扩展网页媒体播放器
  15. element中file-upload组件的提示‘按delete键可删除’,怎么去掉
  16. oppo小布机器人_看这一篇就够了,1分钟带你了解OPPO小布的隐藏玩法!
  17. SqlServer 对象名无效的解决方法
  18. python 正则表达式生成器_正则表达式生成器
  19. 随笔3:有调节的中介示例之 Model 1
  20. 集成MOB 社会分享遇到的坑

热门文章

  1. 06-一些键鼠和页面操作
  2. 浦东新区社区事务受理服务中心一览表
  3. 支付系统之应用内支付
  4. 对校招生培养工作的建议_招生工作总结
  5. SQL:对表、字段起别名
  6. mySql获取表的字段名,字段注释
  7. MacOS操作系统使用-小白到熟练掌握
  8. combox获取mysql_C# 查询mysql数据库并绑定至combox中
  9. 2021年G3锅炉水处理考试总结及G3锅炉水处理复审考试
  10. Python的起源和发展