一、引述
网上关于Qt模拟微信、QQ的页面开发的多如牛毛,但C++本身来说逻辑上难上手,对只会Python的小伙伴来说太痛苦了。
今天就为大家开个场(下节更精彩),众所周知,要想模拟微信、QQ等这种聊天工具,最重要之一就是聊天框里的气泡问题。
二、思路
1、UI设计
UI的设计风格与微信页面设计大体相似,主要分成了5大部分:
- 导航栏,消息、用户等点击选择
- 消息栏框,显示好友消息列表
- 聊天页面,显示气泡消息
- 文本框,输入聊天信息
- 聊天工具框,表情、文件等工具栏
2、气泡消息绘画
目前采用的方式单独使用一个QWidget类,重写paintEvent事件,主要有三个部分组成:
- 头像
- 气泡框
- 文本框
其中,气泡框大小、文本框大小决定于文本的大小(包括图片的大小)
3、富文本框(信息输入框)的实现
在这里信息输入框需满足以下要求:
- 普通文本,部件的基本功能,无需实现
- 本地图片,实现复制粘贴的需求
- 网络图片的粘贴,html富文本的格式
- 本地文件的拖拐(copy)
- 表情包,与图片类似
4、服务器实现
暂时以傻瓜式的服务器来实现聊天信息的发送和接受。
- 中间后端服务器service实现,登录以TCP连接方式进行登录。
- 各客户端为Client,发送信息时,以UDP方式发送至中转站服务器,服务器再转发至对方。
三、气泡框思路
我们应该知道在聊天框里,每一天聊天记录都是一个item,这个item里包含了头像和信息这两部分内容。
解决这个难题的方法之一就是使用QPainter来进行画图,然后封装成一个QWidget作为一个item。
而聊天框架则使用QListWidget,每当点击发送按钮,触发添加一个item事件。
思路是这样,但实现起来比较难,为此我从CSDN里找到了一位大佬的推文,虽说是C++的Qt写的,但重写为python,问题不大。
首先,我们先写一个气泡类,重写paintEvent事件,并且在类中自定义了消息文本变量data。
window_height = 10
begin_width_spacing = 20
begin_height_spacing = 16
icon_width = 40
icon_height = 40
text_width_spacing = 12
text_height_spacing = 12
triangle_width = 6
triangle_height = 10
triangle_height_spacing = 10
text_min_width = 0
min_width = 0
text_max_width = 0
real_width = 0
text_height = 0
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None, data='',type_mess = 0):
super(MyWidget, self).__init__(parent)
self.setObjectName('myWidget')
self.user_chat_content = data
# 重写paintEvent 否则不能使用样式表定义外观
def paintEvent(self, event):
self.init_data() # 获取文本长度、气泡框架问题
一个气泡的大小决定于文本的长度(自动换行),因此呢,我们应该先定义font的类型,它的字体和大小。
def init_data(self):
font = QtGui.QFont()
font.setFamily("实体")
font.setPointSize(12)
metrics = QFontMetrics(font)
global text_min_width, min_width,text_max_width,real_width, text_height, window_height
if metrics.width("A") * 2 + begin_height_spacing * 1.5 > text_width_spacing:
text_min_width = begin_height_spacing * 1.5 - text_width_spacing
else:
text_min_width = 0
min_width = begin_width_spacing + icon_width + triangle_width + text_width_spacing + text_width_spacing + icon_width + begin_width_spacing
if self.width()< min_width+text_min_width:
self.setMinimumWidth(min_width + text_min_width)
text_max_width = self.width() - min_width
real_width = metrics.width(self.user_chat_content)
if real_width < text_max_width:
text_max_width = real_width
if text_height_spacing+metrics.height()+text_height_spacing>triangle_height_spacing+triangle_height+triangle_height_spacing:
text_height = metrics.height()
else:
text_height = triangle_height_spacing + triangle_height + triangle_height_spacing
else:
flag = QtCore.Qt.TextWordWrap
textRect = QRect(0, 0, text_max_width, 0)
# 自动换行
textRect = metrics.boundingRect(textRect, flag, self.user_chat_content)
text_height = textRect.height()
初始化完一些气泡的宽度、长度后,接下来就是画气泡的问题了。气泡=头像+信息,但气泡又分为两种,一种是自己发送的消息气泡,而另一种是对方发送的气泡,分别占据右侧和左侧。
因此呢,还需要再添加一个变量才行,用来判定是否是接收方。最后就是调用painter.drawPixmap函数画出头像,painter.drawText来画出文字即可。
好了,今天就为大家开个场,更多精彩点击——>>跳转