最近在做一个微信数据库备份的项目,想做个界面展示聊天记录,奈何一直没有找到用pyqt实现的类似微信的聊天界面,于是就想着自己做一个。
效果
聊天框由四部分组成:最左侧是头像,右侧是聊天内容,中间绘制一个三角形指向头像,最右侧放置一个弹簧控件来调整消息的长度。
头像通过继承QLabel实现,用户可以传入头像路径或QPixmap对象。头像会根据需要进行缩放,并设置固定的大小。
pythonclass Avatar(QLabel):
def __init__(self, avatar, parent=None):
super().__init__(parent)
if isinstance(avatar, str):
self.setPixmap(QPixmap(avatar).scaled(45, 45))
self.image_path = avatar
elif isinstance(avatar, QPixmap):
self.setPixmap(avatar.scaled(45, 45))
self.setFixedSize(QSize(45, 45))
通过继承QLabel实现一个三角形,用于指向头像的方向。根据消息是发送还是接收,绘制不同方向的三角形。
pythonclass Triangle(QLabel):
def __init__(self, Type, is_send=False, parent=None):
super().__init__(parent)
self.Type = Type
self.is_send = is_send
self.setFixedSize(6, 45)
def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
super(Triangle, self).paintEvent(a0)
if self.Type == MessageType.Text:
painter = QPainter(self)
triangle = QPolygon()
if self.is_send:
painter.setPen(QColor('#b2e281'))
painter.setBrush(QColor('#b2e281'))
triangle.setPoints(0, 20, 0, 35, 6, 25)
else:
painter.setPen(QColor('white'))
painter.setBrush(QColor('white'))
triangle.setPoints(0, 25, 6, 20, 6, 35)
painter.drawPolygon(triangle)
通过继承QLabel实现文字消息控件,支持自动换行、文字选择和不同样式的边框。
pythonclass TextMessage(QLabel):
heightSingal = pyqtSignal(int)
def __init__(self, text, is_send=False, parent=None):
super(TextMessage, self).__init__(text, parent)
font = QFont('微软雅黑', 12)
self.setFont(font)
self.setWordWrap(True)
self.setMaximumWidth(800)
self.setMinimumWidth(100)
self.setMinimumHeight(45)
self.setTextInteractionFlags(Qt.TextSelectableByMouse)
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
if is_send:
self.setAlignment(Qt.AlignCenter | Qt.AlignRight)
self.setStyleSheet(
'''
background-color:#b2e281;
border-radius:10px;
padding:10px;
'''
)
else:
self.setStyleSheet(
'''
background-color:white;
border-radius:10px;
padding:10px;
'''
)
font_metrics = QFontMetrics(font)
rect = font_metrics.boundingRect(text)
self.setMaximumWidth(rect.width()+30)
核心是边框样式的设置,self.setWordWrap(True)设置文字自动换行,self.setTextInteractionFlags(Qt.TextSelectableByMouse)设置文字可选中,self.setAlignment(Qt.AlignCenter | Qt.AlignRight)设置文字对齐方式
css{
background-color:#b2e281; // 边框颜色
border-radius:10px; // 边框圆角半径
padding:10px;
}
最后,将头像、三角形和消息控件组合在一起,通过水平布局排列,形成完整的聊天框组件。
pythonclass BubbleMessage(QWidget):
def __init__(self, str_content, avatar, Type, is_send=False, parent=None):
super().__init__(parent)
self.isSend = is_send
# self.set
self.setStyleSheet(
'''
border:none;
'''
)
layout = QHBoxLayout()
layout.setSpacing(0)
layout.setContentsMargins(0, 5, 5, 5)
# self.resize(QSize(200, 50))
self.avatar = Avatar(avatar)
triangle = Triangle(Type, is_send)
if Type == MessageType.Text:
self.message = TextMessage(str_content, is_send)
# self.message.setMaximumWidth(int(self.width() * 0.6))
elif Type == MessageType.Image:
self.message = ImageMessage(str_content)
else:
raise ValueError("未知的消息类型")
self.spacerItem = QSpacerItem(45 + 6, 45, QSizePolicy.Expanding, QSizePolicy.Minimum)
if is_send:
layout.addItem(self.spacerItem)
layout.addWidget(self.message, 1)
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignLeft)
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignLeft)
else:
layout.addWidget(self.avatar, 0, Qt.AlignTop | Qt.AlignRight)
layout.addWidget(triangle, 0, Qt.AlignTop | Qt.AlignRight)
layout.addWidget(self.message, 1)
layout.addItem(self.spacerItem)
self.setLayout(layout)
应用到项目中去:微信聊天记录备份
本文作者:周帅康
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!