PyQt简单示例聊天程序

PyQt简单示例聊天程序

效果展示:

https://s1.ax1x.com/2022/03/25/qYbMwQ.gif

代码:

from PyQt5.Qt import *
from talk import Ui_Form
import socket
import sys
import time

class Window(QWidget,Ui_Form):
    def __init__(self, parent=None, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.setupUi(self)
        ipaddress = Socket_Client.get_ip() #调用类方法进行获取ip
        self.lineEdit_3.setText(ipaddress)
        self.radioButton.setChecked(True)
        self.lineEdit_4.setText("8888")
        self.pushButton.clicked.connect(self.socket_connect)
        self.pushButton_2.clicked.connect(self.send_message)
        self.radioButton.toggled.connect(self.switch_client_server)

    def switch_client_server(self):
        print("switch")
        self.pushButton.clicked.connect(self.socket_server)
        self.pushButton_2.clicked.connect(self.server_send_data)

    def socket_connect(self): #连接按钮绑定函数,建立socket连接
        QCoreApplication.processEvents();
        try:
            self.socket_client = Socket_Client(self.lineEdit_3.text(),int(self.lineEdit_4.text()))
            self.socket_client.client_socket()
            self.setWindowTitle("聊天程序1.0 连接成功")
            self.thread_1 = Thread_recv(self.socket_client,self.textEdit_2)
            self.thread_1.start()
        except Exception as e:
            print(e)
            print("error")
            self.setWindowTitle("聊天程序1.0 连接失败")

    def socket_server(self):  #服务端函数
        QCoreApplication.processEvents();
        try:
            self.server_socket = Socket_Client(self.lineEdit_3.text(),int(self.lineEdit_4.text()))
            self.server_socket.server_socket()
            self.setWindowTitle("聊天程序1.0 服务开启成功")
            self.thread_2 = Thread_sev(self.server_socket,self.textEdit_2)
            self.thread_2.start()
        except Exception as e:
            print(e)
            self.setWindowTitle("聊天程序1.0 服务开启失败")

    def send_message(self):#发送消息

        try:
            self.socket_client.send_data(self.textEdit.toPlainText())
            localtime = time.strftime("%H:%M:%S")
            self.textEdit_2.append(f"[{localtime}]:"+"发送成功!")
            self.textEdit_2.append(f"[{localtime}]:" + "我说:" + self.textEdit.toPlainText() )
            self.textEdit.clear()
            self.textEdit.moveCursor(QTextCursor.End)
        except Exception as e:
            print(e)

    def server_send_data(self):
        try:
            self.server_socket.server_send_data(self.textEdit.toPlainText())
            localtime = time.strftime("%H:%M:%S")
            self.textEdit_2.append(f"[{localtime}]:" + "发送成功!")
            self.textEdit_2.append(f"[{localtime}]:" + "我说:" + self.textEdit.toPlainText())
            self.textEdit.clear()
            self.textEdit.moveCursor(QTextCursor.End)
        except Exception as e:
            print(e)

class Thread_recv(QThread):
    def __init__(self, recv,text_edit):
        super().__init__()
        self.recv = recv
        self.text_edit = text_edit

    def run(self):
        while True:
            self.recv_data = self.recv.recv_data()
            print(self.recv_data)
            localtime = time.strftime("%H:%M:%S")
            self.text_edit.append( f"[{localtime}]:" +"对方说:"+ self.recv_data)

class Thread_sev(QThread):
    def __init__(self,server_socket,text_edit):
        super().__init__()
        self.server = server_socket
        self.text = text_edit

    def run(self):
        self.server.server_accept()
        print(self.server.client_ip_port)
        localtime = time.strftime("%H:%M:%S")
        self.text.append(f"[{localtime}]:" + f"客户端连接成功:{self.server.client_ip_port[0]}")
        while True:
            self.data = str(self.server.client.recv(1024),"gbk")
            print(self.data)
            localtime = time.strftime("%H:%M:%S")
            self.text.append(f"[{localtime}]:" + "对方说:" + self.data)

class Socket_Client(object):
    def __init__(self,ipadress,port):
        self.ipaddress = ipadress
        self.port = port

    @classmethod
    def get_ip(cls):
        socket_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            socket_ip.connect(('10.255.255.255', 1))
            return socket_ip.getsockname()[0]
        except Exception:
            return '127.0.0.1'
        finally:
            socket_ip.close()

    def client_socket(self):
        self.client_connect = socket.socket(family=-1,type=-1)
        self.client_connect.connect((self.ipaddress,self.port))

    def close_socket(self):
        self.client_connect.close()

    def server_socket(self):
        self.server_connect = socket.socket(family=-1,type=-1)
        self.server_connect.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        self.server_connect.bind((self.ipaddress,self.port))
        self.server_connect.listen(128)

    def server_accept(self):
        self.client,self.client_ip_port = self.server_connect.accept()

    def server_send_data(self,data):
        data = data.encode('gbk')
        print(data)
        self.client.send(data)

    def send_data(self,data):
        data = data.encode('gbk')  #进行gbk编码
        print(data)
        self.client_connect.send(data)

    def recv_data(self):
        recv = str(self.client_connect.recv(1024),'gbk') #以gbk方式转码
        return recv

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window =   Window()
    window.setWindowTitle("聊天程序1.0")
    window.show()
    sys.exit(app.exec())

界面示意图:

https://s1.ax1x.com/2022/03/25/qYOPwF.png

界面代码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\Administrator\Desktop\qt\talk\talk.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 300)
        self.pushButton = QtWidgets.QPushButton(Form)
        self.pushButton.setGeometry(QtCore.QRect(290, 40, 93, 28))
        self.pushButton.setObjectName("pushButton")
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(290, 90, 93, 28))
        self.pushButton_2.setObjectName("pushButton_2")
        self.lineEdit = QtWidgets.QLineEdit(Form)
        self.lineEdit.setGeometry(QtCore.QRect(20, 10, 31, 20))
        self.lineEdit.setObjectName("lineEdit")
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setGeometry(QtCore.QRect(20, 150, 31, 20))
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.radioButton = QtWidgets.QRadioButton(Form)
        self.radioButton.setGeometry(QtCore.QRect(300, 130, 93, 31))
        self.radioButton.setObjectName("radioButton")
        self.radioButton_2 = QtWidgets.QRadioButton(Form)
        self.radioButton_2.setGeometry(QtCore.QRect(300, 160, 93, 31))
        self.radioButton_2.setObjectName("radioButton_2")
        self.lineEdit_3 = QtWidgets.QLineEdit(Form)
        self.lineEdit_3.setGeometry(QtCore.QRect(280, 220, 111, 31))
        self.lineEdit_3.setText("")
        self.lineEdit_3.setObjectName("lineEdit_3")
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(310, 200, 54, 12))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(290, 260, 41, 21))
        font = QtGui.QFont()
        font.setFamily("Arial")
        self.label_2.setFont(font)
        self.label_2.setLayoutDirection(QtCore.Qt.RightToLeft)
        self.label_2.setAutoFillBackground(False)
        self.label_2.setObjectName("label_2")
        self.lineEdit_4 = QtWidgets.QLineEdit(Form)
        self.lineEdit_4.setGeometry(QtCore.QRect(320, 260, 61, 21))
        self.lineEdit_4.setObjectName("lineEdit_4")
        self.textEdit = QtWidgets.QTextEdit(Form)
        self.textEdit.setGeometry(QtCore.QRect(20, 40, 241, 101))
        self.textEdit.setObjectName("textEdit")
        self.textEdit_2 = QtWidgets.QTextEdit(Form)
        self.textEdit_2.setGeometry(QtCore.QRect(20, 180, 241, 101))
        self.textEdit_2.setObjectName("textEdit_2")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton.setText(_translate("Form", "连接/开启"))
        self.pushButton_2.setText(_translate("Form", "发送"))
        self.lineEdit.setText(_translate("Form", "发送"))
        self.lineEdit_2.setText(_translate("Form", "接收"))
        self.radioButton.setText(_translate("Form", "客户端"))
        self.radioButton_2.setText(_translate("Form", "服务端"))
        self.label.setText(_translate("Form", "ip地址"))
        self.label_2.setToolTip(_translate("Form", "<html><head/><body><p align=\"center\"><br/></p></body></html>"))
        self.label_2.setText(_translate("Form", "端口"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())

思路:

1.使用PyQT和Socket库

先初始化ui界面:

class Window(QWidget,Ui_Form):
    def __init__(self, parent=None, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.setupUi(self)
        ipaddress = Socket_Client.get_ip() #获取ip
        self.lineEdit_3.setText(ipaddress)
        self.radioButton.setChecked(True)
        self.lineEdit_4.setText("8888")
        self.pushButton.clicked.connect(self.socket_connect)
        self.pushButton_2.clicked.connect(self.send_message)
        self.radioButton.toggled.connect(self.switch_client_server)

然后绑定两个按钮的点击信号的槽函数:

	self.pushButton.clicked.connect(self.socket_connect)
  self.pushButton_2.clicked.connect(self.send_message)

创建socket类当运行槽函数时创建服务端或客户端:

class Socket_Client(object):
    def __init__(self,ipadress,port): #当类初始化时填入ip地址和端口号
        self.ipaddress = ipadress
        self.port = port

    @classmethod
    def get_ip(cls): #获取初始化的ip地址,获取不到填入127.0.0.1
        socket_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            socket_ip.connect(('10.255.255.255', 1))
            return socket_ip.getsockname()[0]
        except Exception:
            return '127.0.0.1'
        finally:
            socket_ip.close()

    def client_socket(self):  #创建客户端的socket通信
        self.client_connect = socket.socket(family=-1,type=-1)
        self.client_connect.connect((self.ipaddress,self.port))

    def close_socket(self):   #关闭socket连接
        self.client_connect.close()

    def server_socket(self): #创建服务端的sockett通信
        self.server_connect = socket.socket(family=-1,type=-1)
        self.server_connect.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        self.server_connect.bind((self.ipaddress,self.port))
        self.server_connect.listen(128)

    def server_accept(self):#服务端的监听函数
        self.client,self.client_ip_port = self.server_connect.accept()

    def server_send_data(self,data): #服务端发送函数
        data = data.encode('gbk')
        print(data)
        self.client.send(data)

    def send_data(self,data):#客户端发送数据函数
        data = data.encode('gbk')  #进行gbk编码
        print(data)
        self.client_connect.send(data)

    def recv_data(self):#客户端监听函数
        recv = str(self.client_connect.recv(1024),'gbk') #以gbk方式转码
        return recv

分别创建客户端和服务端的发送按钮和开启按钮的槽函数:

def socket_connect(self): #连接按钮绑定函数,建立socket连接
        QCoreApplication.processEvents();
        try:
            self.socket_client = Socket_Client(self.lineEdit_3.text(),int(self.lineEdit_4.text()))
            self.socket_client.client_socket()
            self.setWindowTitle("聊天程序1.0 连接成功")
            self.thread_1 = Thread_recv(self.socket_client,self.textEdit_2 #创建子进程
            self.thread_1.start()#开启子进程
        except Exception as e:
            print(e)
            print("error")
            self.setWindowTitle("聊天程序1.0 连接失败")

    def socket_server(self):  #服务端函数
        QCoreApplication.processEvents();
        try:
            self.server_socket = Socket_Client(self.lineEdit_3.text(),int(self.lineEdit_4.text()))
            self.server_socket.server_socket()
            self.setWindowTitle("聊天程序1.0 服务开启成功")
            self.thread_2 = Thread_sev(self.server_socket,self.textEdit_2) #创建子进程
            self.thread_2.start() #开启子进程
        except Exception as e:
            print(e)
            self.setWindowTitle("聊天程序1.0 服务开启失败")

    def send_message(self):#发送消息

        try:
            self.socket_client.send_data(self.textEdit.toPlainText())
            localtime = time.strftime("%H:%M:%S")
            self.textEdit_2.append(f"[{localtime}]:"+"发送成功!") 
            self.textEdit_2.append(f"[{localtime}]:" + "我说:" + self.textEdit.toPlainText() )
            self.textEdit.clear()
            self.textEdit.moveCursor(QTextCursor.End)
        except Exception as e:
            print(e)

    def server_send_data(self):
        try:
            self.server_socket.server_send_data(self.textEdit.toPlainText())
            localtime = time.strftime("%H:%M:%S")
            self.textEdit_2.append(f"[{localtime}]:" + "发送成功!")
            self.textEdit_2.append(f"[{localtime}]:" + "我说:" + self.textEdit.toPlainText())
            self.textEdit.clear()
            self.textEdit.moveCursor(QTextCursor.End)
        except Exception as e:
            print(e)

然后创建俩个QT线程,因为PYQT主线程用来绘制GUI界面,如果有创造一些耗时的函数,在主线程中执行,那么界面很容易就卡死,解决的方法一般有两个,一个是创造线程,进程,一个就是调用QCoreApplication.processEvents(),来让GUI界面防止卡死,但是遇到阻塞函数,还是一样会卡死。在socket中的接收消息的过程中,就需要一直等待接收,只能放到子线程中去执行。

class Thread_recv(QThread):  #客户端等待接收消息的线程
    def __init__(self, recv,text_edit):
        super().__init__()
        self.recv = recv
        self.text_edit = text_edit

    def run(self):
        while True:
            self.recv_data = self.recv.recv_data()
            print(self.recv_data)
            localtime = time.strftime("%H:%M:%S")
            self.text_edit.append( f"[{localtime}]:" +"对方说:"+ self.recv_data)

class Thread_sev(QThread):  #服务端等待连接的线程
    def __init__(self,server_socket,text_edit):
        super().__init__()
        self.server = server_socket
        self.text = text_edit

    def run(self):
        self.server.server_accept()
        print(self.server.client_ip_port)
        localtime = time.strftime("%H:%M:%S")
        self.text.append(f"[{localtime}]:" + f"客户端连接成功:{self.server.client_ip_port[0]}")
        while True:
            self.data = str(self.server.client.recv(1024),"gbk")
            print(self.data)
            localtime = time.strftime("%H:%M:%S")
            self.text.append(f"[{localtime}]:" + "对方说:" + self.data)

最后加一个选择按钮的切换状态槽函数和主函数:

def switch_client_server(self):
        print("switch")
        self.pushButton.clicked.connect(self.socket_server)
        self.pushButton_2.clicked.connect(self.server_send_data)
if __name__ == '__main__':

    app = QApplication(sys.argv)
    window =   Window()
    window.setWindowTitle("聊天程序1.0")
    window.show()
    sys.exit(app.exec())

总结:

pyqt的界面非常容易卡死,所以在写程序的时候,多线程是必不可少的。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我很乐意给你写一个 PyQt5聊天程序。首先,我会使用 PyQt5 来创建一个窗口,用于显示聊天内容和输入框,然后添加一个按钮来发送消息。之后,我将使用 Qt 的消息机制来实现一个套接字,以便客户端和服务器之间的通信,并利用多线程来处理客户端的聊天信息。最后,我将使用 SQLite 来存储历史聊天信息,并实现一个聊天记录的功能。 ### 回答2: PyQt5 是一种用于创建图形用户界面的 Python 库,可以用于开发各种类型的应用程序,包括聊天程序。下面是一个简单的例子,展示了如何使用 PyQt5 创建一个聊天程序。 首先,我们需要导入必要的模块和类: ```python import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * ``` 然后,我们创建一个 QMainWindow 类来作为应用程序的主窗口: ```python class ChatWindow(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle("聊天程序") self.setGeometry(100, 100, 400, 300) self.setCentralWidget(QWidget(self)) ``` 接下来,我们创建一个 QVBoxLayout,用于将多个聊天消息显示在垂直布局中: ```python self.layout = QVBoxLayout() self.centralWidget().setLayout(self.layout) ``` 然后,我们创建一个 QLineEdit 和一个 QPushButton,用于输入消息和发送消息: ```python self.input = QLineEdit(self) self.layout.addWidget(self.input) self.sendButton = QPushButton("发送", self) self.sendButton.clicked.connect(self.sendMessage) self.layout.addWidget(self.sendButton) ``` 然后,我们创建一个 QTextEdit,用于显示收到的消息: ```python self.output = QTextEdit(self) self.output.setReadOnly(True) self.layout.addWidget(self.output) ``` 最后,我们实现 sendMessage() 方法,用于将输入的消息显示在 QTextEdit 中: ```python def sendMessage(self): message = self.input.text() self.output.append(message) self.input.clear() ``` 现在,我们可以创建一个 QApplication 对象,并在其中实例化 ChatWindow 类,然后运行应用程序: ```python if __name__ == "__main__": app = QApplication(sys.argv) window = ChatWindow() window.show() sys.exit(app.exec_()) ``` 通过运行这个简单聊天程序,你可以在窗口中输入消息,然后点击“发送”按钮将其显示在聊天窗口中。 请注意,这只是一个简单的例子,实际的聊天程序可能需要更复杂的功能,如网络连接和多人聊天等。 ### 回答3: PyQt5是一个功能强大的Python界面开发工具包,可以使用它来创建聊天程序。下面是一个用PyQt5实现的简单聊天程序示例: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit, QPushButton, QVBoxLayout, QWidget class ChatWindow(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("聊天程序") self.resize(300, 400) # 创建文本编辑框 self.text_edit = QTextEdit() self.text_edit.setReadOnly(True) # 创建发送按钮 self.send_button = QPushButton("发送") self.send_button.clicked.connect(self.send_message) # 创建垂直布局 layout = QVBoxLayout() layout.addWidget(self.text_edit) layout.addWidget(self.send_button) # 创建中心部件,设置布局 central_widget = QWidget() central_widget.setLayout(layout) self.setCentralWidget(central_widget) def send_message(self): input_text = self.text_edit.toPlainText() # 在这里添加发送消息的逻辑 self.text_edit.clear() if __name__ == "__main__": app = QApplication(sys.argv) window = ChatWindow() window.show() sys.exit(app.exec_()) ``` 这个程序创建了一个带有文本编辑框和发送按钮的聊天窗口。用户在文本编辑框中输入消息后,可以点击发送按钮发送消息。你需要根据具体需求,在`send_message`方法中添加发送消息的逻辑,比如将消息发送到服务器或其他客户端。 这只是一个简单示例程序,你还可以根据自己的需求进行更详细的定制。希望这个示例对你有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值