基于PyQt5实现聊天窗口

本文仅为示例,用于参考,功能并不完整

主要实现以下功能:

1.重写PlainTextEdit组件实现类似微信ctrl+enter换行,enter发送信息操作

2.带头像的消息气泡创建

3.消息气泡的自适应大小


窗口布局(详细可以通过示例代码中的.ui进行查看)


代码获取地址

GitHub:PyQt5-Chat-Demo

百度网盘:https://pan.baidu.com/s/1Pi06nAeOo9sWiNaaHgC86w?pwd=ayhf

image


代码详解(请先获取代码方便对照)

1.窗口初始化与定义

主要操作:初始化,定义信号与槽

class MainWindow(QMainWindow,Ui_MainWindow):
    def __init__(self,parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.sum=0                                                  #气泡数量
        self.widgetlist = []                                        #记录气泡
        self.text = ""                                              # 存储信息
        self.icon = QtGui.QPixmap("1.jpg")                          # 头像
        #设置聊天窗口样式 隐藏滚动条
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        # 信号与槽
        self.pushButton.clicked.connect(self.create_widget)         #创建气泡
        self.pushButton.clicked.connect(self.set_widget)            #修改气泡长宽
        self.plainTextEdit.undoAvailable.connect(self.Event)        #监听输入框状态
        scrollbar = self.scrollArea.verticalScrollBar()
        scrollbar.rangeChanged.connect(self.adjustScrollToMaxValue) #监听窗口滚动条范围

2.回车发送的实现

用户回车->plainTextEdit声明于PlainTextEdit_Rewite.py的重写方法被激活->初始化函数的信号监听到->执行槽函数

主要操作:模拟发送点击事件(会导致TextEdit焦点消失),TextEdit重新设置焦点

    # 回车绑定发送
    def Event(self):	#注意,这个方法是先通过了PlainTextEdit_Rewite.py的重写方法激活了上方代码的信号,才执行的槽函数
        if not self.plainTextEdit.isEnabled():     #当PlainTextEdit处于禁用状态执行下面代码
            self.plainTextEdit.setEnabled(True)
            self.pushButton.click()
            self.plainTextEdit.setFocus()

Qt5没有原生的回车发送的方法,试过很多方法,对比来看,用信号监听plainTextEdit的状态是最稳定且方便的


3.生成气泡并插入scrollArea

调用new_widget.py下set_return方法创建新组件并插入scrollArea

    #创建气泡
    def create_widget(self):
        self.text=self.plainTextEdit.toPlainText()
        self.plainTextEdit.setPlainText("")
        self.sum += 1
        if self.sum % 2:   # 根据判断创建左右气泡
            Set_question.set_return(self, self.icon, self.text,QtCore.Qt.LeftToRight)    # 调用new_widget.py中方法生成左气泡
            QApplication.processEvents()                                # 等待并处理主循环事件队列
        else:
            Set_question.set_return(self, self.icon, self.text,QtCore.Qt.RightToLeft)   # 调用new_widget.py中方法生成右气泡
            QApplication.processEvents()                                # 等待并处理主循环事件队列

窗口组件的层级关系请看上方窗口布局


4.修改气泡组件长宽

Qt5组件的更新方式比较奇怪,只有在气泡组件创建完成后才能获取到文本框适应的宽高,所以这里是在创建好后再进行修改,可以看到修改方式比较傻瓜,但起码效果还是能看的

    # 修改气泡长宽
    def set_widget(self):
        font = QFont()
        font.setPointSize(16)
        fm = QFontMetrics(font)
        text_width = fm.width(self.text)+115    #根据字体大小生成适合的气泡宽度
        if self.sum != 0:
            if text_width>632:                  #宽度上限
                text_width=int(self.textBrowser.document().size().width())+100  #固定宽度
            self.widget.setMinimumSize(text_width,int(self.textBrowser.document().size().height())+ 40) #规定气泡大小
            self.widget.setMaximumSize(text_width,int(self.textBrowser.document().size().height())+ 40) #规定气泡大小
            self.scrollArea.verticalScrollBar().setValue(10)

5.窗口自动滚动

信号监听窗口滚动条范围,执行此槽函数

    # 窗口滚动到最底部
    def adjustScrollToMaxValue(self):
        scrollbar = self.scrollArea.verticalScrollBar()
        scrollbar.setValue(scrollbar.maximum())

布局文件的改动(注意)

因为本示例重写了QPlainTextEdit,所以如果你通过PyUIC重新生成了布局文件,需要在布局文件中将组件的声明也修改掉。

PyUIC生成的代码

self.plainTextEdit = QtWidgets.QPlainTextEdit(self.centralwidget)

修改为

from PlainTextEdit_Rewite import MyPlainTextEdit

self.plainTextEdit = MyPlainTextEdit(self.frame)

以本文作为示例可以制作一个chatgpt的桌面聊天软件

image

END 😃

posted @   Rrea  阅读(2004)  评论(7编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示