当前位置:   article > 正文

python实现的聊天室(二)_pyqt5成功实现聊天室

pyqt5成功实现聊天室

python实现的聊天室(二)

1、前言

我在python实现的聊天室(一)一文中实现了一个没有界面的聊天室,所有操作都在CMD命令行下进行,用户体验比较差。所以在这一篇文章中,主要实现一个有界面的聊天室。

2、需求分析

我们要实现的分为两部分:

  • 服务器:负责与用户建立 Socket 连接,并将某个用户发送的消息广播到所有在线的用户。显示用户进入/退出聊天室信息。
  • 客户端:可以输入聊天的内容并发送,同时可以显示其他用户的消息记录。

3、服务端实现

# -*- coding: gbk -*-  
from PyQt4.QtGui import *  
from PyQt4.QtCore import *  
import sys  
from PyQt4.QtNetwork import *  
import locale	  
#QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))	  
class TcpClientSocket(QTcpSocket):  
    def __init__(self,parent=None):  
        super(TcpClientSocket,self).__init__(parent)  
        self.connect(self,SIGNAL("readyRead()"),self.dataReceive)  
        self.connect(self,SIGNAL("disconnected()"),self.slotDisconnected)  
        self.length = 0  
        self.msglist = QByteArray()  	      
    def dataReceive(self):  
        while self.bytesAvailable() > 0:  
            length = self.bytesAvailable()  
            msg = self.read(length)  
            self.emit(SIGNAL("updateClients(QString,int)"),msg,length)  	                      
    def slotDisconnected(self):  
        pass  	          
class Server(QTcpServer):  
    def __init__(self,parent=None,port=0):  
        super(Server,self).__init__(parent)  
        self.listen(QHostAddress.Any,port)  
        self.tcpClientSocketList = []  	      
    def incomingConnection(self,socketDescriptor):  
        tcpClientSocket = TcpClientSocket(self)  
        	        self.connect(tcpClientSocket,SIGNAL("updateClients(QString,int)"),self.updateClients)  
        	        	        self.connect(tcpClientSocket,SIGNAL("disconnetcted(int)"),self.slotDisconnected)  
        tcpClientSocket.setSocketDescriptor(socketDescriptor)  
        self.tcpClientSocketList.append(tcpClientSocket)        
    def updateClients(self,msg,length):  
        self.emit(SIGNAL("updateServer(QString,int)"),msg,length)  
        for i in xrange(len(self.tcpClientSocketList)):  
            item = self.tcpClientSocketList[i]
            length_msg = item.writeData(msg)			
            #length_msg = item.writeData(msg.toUtf8())  
            #if length_msg != msg.toUtf8().length():  
            #    continue  					      
    def slotDisconnected(self,descriptor):  
        for i in xrange(len(self.tcpClientSocketList)):  
            item = self.tcpClientSocketList[i]  
            if item.socketDescriptor() == descriptor:  
                self.tcpClientSocketList.remove[i]  
                return  
        return    
class TcpServer(QDialog):  
    def __init__(self,parent=None,f=None):  
        super(TcpServer,self).__init__(parent)  
        self.setWindowTitle("服务端")  
        vbMain = QVBoxLayout(self)  
        self.ListWidgetContent = QListWidget(self)  
        vbMain.addWidget(self.ListWidgetContent)  	          
        hb = QHBoxLayout()  
        LabelPort = QLabel(self)  
        LabelPort.setText(self.tr("Port:"))  
        hb.addWidget(LabelPort)  	          
        LineEditPort = QLineEdit(self)  
        hb.addWidget(LineEditPort)  	          
        vbMain.addLayout(hb)  	          
        self.PushButtonCreate = QPushButton(self)  
        self.PushButtonCreate.setText(self.tr("创建聊天室"))  
        vbMain.addWidget(self.PushButtonCreate)  
          	        self.connect(self.PushButtonCreate,SIGNAL("clicked()"),self.slotCreateServer)  
        self.port  = 8010  
        LineEditPort.setText(QString.number(self.port))  	      
    def slotCreateServer(self):  
        server = Server(self,self.port)  
        self.connect(server,SIGNAL("updateServer(QString,int)"),self.updateServer)  
        self.PushButtonCreate.setEnabled(False)  	      
    def updateServer(self,msg,length):  
        #self.ListWidgetContent.addItem(msg.fromUtf8(msg))  
		self.ListWidgetContent.addItem(msg) 	                                 
if __name__ == '__main__':             
	app=QApplication(sys.argv)	
	mycode = locale.getpreferredencoding()
	code = QTextCodec.codecForName(mycode)
	QTextCodec.setCodecForLocale(code)
	QTextCodec.setCodecForTr(code)
	QTextCodec.setCodecForCStrings(code)		
	dialog=TcpServer()  
	dialog.show()  
	app.exec_()  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

4、客户端实现

# -*- coding: gbk -*-  
from PyQt4.QtGui import *  
from PyQt4.QtCore import *  
import sys  
from PyQt4.QtNetwork import *  
import locale  
#QTextCodec.setCodecForTr(QTextCodec.codecForName("utf8"))  	  
class TcpClient(QDialog):  
    def __init__(self,parent=None):  
        super(TcpClient,self).__init__(parent)  
        self.setWindowTitle(self.tr("客户端"))    	          
        self.status = False   
        self.serverIP = QHostAddress()  
        self.port = 8010  
        self.msglist = QByteArray()  	          
        vbMain = QVBoxLayout(self)  
        self.ListWidgetContent = QListWidget(self)  
        vbMain.addWidget(self.ListWidgetContent)  	          
        hb = QHBoxLayout()  
        self.LineEditMessage = QLineEdit(self)  
        hb.addWidget(self.LineEditMessage)  
        self.PushButtonSend = QPushButton(self)  
        self.PushButtonSend.setText(self.tr("发送"))  
        self.PushButtonSend.setEnabled(False)  
        hb.addWidget(self.PushButtonSend)  
        self.connect(self.PushButtonSend,SIGNAL("clicked()"),self.slotSend)  	          
        hb1 = QHBoxLayout()  
        LabelName = QLabel(self)  
        LabelName.setText(self.tr("用户名:"))  
        self.LineEditUser = QLineEdit(self)  
        hb1.addWidget(LabelName)  
        hb1.addWidget(self.LineEditUser)  	          
        hb2 = QHBoxLayout()  
        LabelServerIP = QLabel(self)  
        LabelServerIP.setText(self.tr("服务器地址:"))  
        self.LineEditIP = QLineEdit(self)  
        hb2.addWidget(LabelServerIP)  
        hb2.addWidget(self.LineEditIP)   	          
        hb3 = QHBoxLayout()  
        LabelPort = QLabel(self)  
        LabelPort.setText(self.tr("端口:")) 	          
        self.LineEditPort = QLineEdit(self)  
        hb3.addWidget(LabelPort)  
        hb3.addWidget(self.LineEditPort)   	          
        vbMain.addLayout(hb)  
        vbMain.addLayout(hb1)  
        vbMain.addLayout(hb2)  
        vbMain.addLayout(hb3)  	          
        self.PushButtonLeave = QPushButton(self)  
        self.PushButtonLeave.setText(self.tr("进入聊天室"))  
        vbMain.addWidget(self.PushButtonLeave)  	          
        self.connect(self.PushButtonLeave,SIGNAL("clicked()"),self.slotEnter)  	          
    def slotSend(self):  
        msg = self.userName + ":" + self.LineEditMessage.text(		
        #length = self.tcpSocket.writeData(msg.toUtf8())
        length = self.tcpSocket.writeData(msg)		
        self.LineEditMessage.clear()   
        #if length != msg.toUtf8().length():  
        #    return    	          
    def slotEnter(self):  
        if not self.status:  
            ip = self.LineEditIP.text()  
            if not self.serverIP.setAddress(ip):  
                QMessageBox.information(self,self.tr("error"),self.tr("server ip address error!"))  
                return  
            if self.LineEditUser.text() == "":  
                QMessageBox.information(self,self.tr("error"),self.tr("User Name error!"))  
                return  
            self.userName = self.LineEditUser.text()  
            self.tcpSocket = QTcpSocket(self)  
            self.connect(self.tcpSocket,SIGNAL("connected()"),self.slotConnected)  
            self.connect(self.tcpSocket,SIGNAL("disconnected()"),self.slotDisconnected)  
            self.connect(self.tcpSocket,SIGNAL("readyRead()"),self.dataReceived)              
            self.tcpSocket.connectToHost(self.serverIP.toString(),8010)  
            self.status = True  
        else:  
            msg = self.userName + ":" + self.tr("离开聊天室") 
            length = self.tcpSocket.writeData(msg)			
            #length = self.tcpSocket.writeData(msg.toUtf8()) 			
            #if length != msg.toUtf8().length():  
            #    return                
            self.tcpSocket.disconnectFromHost()  
            self.status = False  	      
    def slotConnected(self):  
        self.PushButtonSend.setEnabled(True)  
        self.PushButtonLeave.setText(self.tr("离开聊天室"))  	          
        msg = self.userName + ":" + self.tr("进入聊天室")  
        #length = self.tcpSocket.writeData(msg.toUtf8())
        length = self.tcpSocket.writeData(msg)		
        #if length != msg.toUtf8().length():  
        #    return  	      
    def slotDisconnected(self):  
        self.PushButtonSend.setEnabled(False)  
        self.PushButtonLeave.setText(self.tr("进入聊天室"))  
    def dataReceived(self):  
        while self.tcpSocket.bytesAvailable() > 0:  
            length = self.tcpSocket.bytesAvailable()  
            msg = QString(self.tcpSocket.read(length))  
            #msg = msg.fromUtf8(msg)  
            #self.ListWidgetContent.addItem(msg.fromUtf8(msg))
            self.ListWidgetContent.addItem(msg)				          	  
if __name__ == '__main__':  
	app=QApplication(sys.argv) 	
	mycode = locale.getpreferredencoding()
	code = QTextCodec.codecForName(mycode)
	QTextCodec.setCodecForLocale(code)
	QTextCodec.setCodecForTr(code)
	QTextCodec.setCodecForCStrings(code)		
	dialog=TcpClient()  
	dialog.show()  
	app.exec_()  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

5、运行效果

运行时先启动服务端,再运行客户端。服务器启动后创建聊天室。客户端运行后,输入昵称、服务器的IP及port信息,进入聊天室。此时服务端会提示用户进入聊天室。当客户端关闭,表明该用户退出聊天室,服务器会转发该用户退出消息到各个客户端。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TLWfRAnb-1593526750899)(http://odsh9s4s2.bkt.clouddn.com/mypyqtchatserver.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XLahNRDt-1593526750901)(http://odsh9s4s2.bkt.clouddn.com/mypyqtchatclientA.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xB06qmLF-1593526750903)(http://odsh9s4s2.bkt.clouddn.com/mypyqtchatclientB.png)]

6、参考链接

因为代码中用到了汉字,所以涉及到编码问题。希望该链接能帮助到你。
http://blog.csdn.net/uselym/article/details/51867056
526750901)]
[外链图片转存中…(img-xB06qmLF-1593526750903)]

6、参考链接

因为代码中用到了汉字,所以涉及到编码问题。希望该链接能帮助到你。
http://blog.csdn.net/uselym/article/details/51867056

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/686397
推荐阅读
相关标签
  

闽ICP备14008679号