您的位置:首页 > 编程语言 > Qt开发

pyqt5实现简单的 p2p聊天

2018-01-20 10:44 197 查看
UI.py(简单的前端界面实现)

import sys
from PyQt5.QtCore import*
from PyQt5.QtWidgets import *
from newClient import*
from PyQt5.QtGui import QIcon
#主页
class MainPage(QWidget):

def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setGeometry(500, 50, 0, 0)
self.setWindowTitle('')
self.setWindowIcon(QIcon('icon.jpg'))
self.resize(300,300)
self.loginButton = QPushButton(self)
self.loginButton.setText("登陆")          #text
self.loginButton.setIcon(QIcon("close.png")) #icon
self.loginButton.setShortcut('Ctrl+D')  #shortcut key
self.loginButton.clicked.connect(self.close)
self.loginButton.setToolTip("Login") #Tool tip
self.loginButton.move(50,100)

self.registerButton = QPushButton(self)
self.registerButton.setText("注册")          #text
self.registerButton.setIcon(QIcon("close.png")) #icon
self.registerButton.setShortcut('Ctrl+D')  #shortcut key
self.registerButton.clicked.connect(self.close)
self.registerButton.setToolTip("Register") #Tool tip
self.registerButton.move(150,100)
self.show()
#跳转到登陆界面
class Login(QWidget):

def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
self.setGeometry(500, 50, 0, 0)
self.setWindowTitle('登陆界面')
self.setWindowIcon(QIcon('icon.jpg'))
self.resize(400,300)
layout = QGridLayout()
nameLabel = QLabel("用户名")
self.nameLineEdit = QLineEdit(" ")
passWordLabel = QLabel("密码")
self.passWordLineEdit = QLineEdit(" ")
self.confirmButton = QPushButton("确定")
self.cancelButton = QPushButton("取消")
self.cancelButton.resize(50,50)
self.confirmButton.clicked.connect(self.addUser)
layout.addWidget(nameLabel,1,0)
layout.addWidget(self.nameLineEdit,1,1)
layout.addWidget(passWordLabel,2,0)
layout.addWidget(self.passWordLineEdit,2,1)
layout.addWidget(self.confirmButton)
layout.addWidget(self.cancelButton)
layout.setColumnStretch(1, 2)
self.setLayout(layout)
def handle_click(self):
if not self.isVisible():
self.show()
def addUser(self):
pList = []
pList.append(self.nameLineEdit.text)
pList.append(self.passWordLineEdit)
loginAndSend(pList)
#注册界面
class Register(QWidget):
registerSignal = pyqtSignal(list)
def __init__(self):
super().__init__()

self.initUI()

def bindSignal(self,func):
self.registerSignal.connect(func)

def initUI(self):
self.setGeometry(500, 50, 0, 0)
self.setWindowTitle('注册界面')
self.setWindowIcon(QIcon('icon.jpg'))
self.resize(300,300)
layout = QGridLayout()
nameLabel = QLabel("用户名")
self.nameLineEdit = QLineEdit("")
passWordLabel1 = QLabel("密码")
self.passWordLineEdit1 = QLineEdit("")
passWordLabel2 = QLabel("确定密码")
self.passWordLineEdit2 = QLineEdit("")
ipAddress = QLabel("IP地址")
self.ipAddressEdit =QLineEdit("")
ipPort = QLabel("端口")
self.ipPortEdit = QLineEdit("")
self.confirmButton = QPushButton("确定")
self.cancelButton = QPushButton("取消")
self.cancelButton.resize(50,50)
layout.addWidget(nameLabel,1,0)
layout.addWidget(self.nameLineEdit,1,1)
layout.addWidget(passWordLabel1,2,0)
layout.addWidget(self.passWordLineEdit1,2,1)
layout.addWidget(passWordLabel2,3,0)
layout.addWidget(self.passWordLineEdit2,3,1)
layout.addWidget(ipAddress,4,0)
layout.addWidget(self.ipAddressEdit,4,1)
layout.addWidget(ipPort,5,0)
layout.addWidget(self.ipPortEdit,5,1)
layout.addWidget(self.confirmButton)
layout.addWidget(self.cancelButton)
layout.setColumnStretch(1, 3)
self.setLayout(layout)

def sendData(self):
pList =[]
pList.append(str(self.nameLineEdit.text()))
pList.append(str(self.passWordLineEdit1.text()))
pList.append(str(self.passWordLineEdit2.text()))
re = registerAndSend(pList)
if re:
print("注册成功")

def handle_click(self):
if not self.isVisible():
self.show()
class chatPage(QMainWindow):
inputSigal = pyqtSignal(str)
sendMesSignal = pyqtSignal(str)
def __init__(self):
super().__init__()

self.initUI()

def initUI(self):
self.setGeometry(800, 50, 0, 0)
self.setWindowTitle('')
self.setWindowIcon(QIcon('icon.jpg'))
self.resize(300,600)
#设置中心窗口
componudWidget = QWidget()
layout = QGridLayout()
self.inputText = QTextEdit("输入聊天信息")
self.inputText.resize(100,100)
self.inputConButton = QPushButton("发送消息")
self.inputCanBUtton = QPushButton("取消发送")
self.showText = QTextEdit("message is here")
self.showText.resize(100,100)
layout.addWidget(self.showText)
layout.addWidget(self.inputText)
layout.addWidget(self.inputConButton)
layout.addWidget(self.inputCanBUtton)
componudWidget.setLayout(layout)
self.setCentralWidget(componudWidget)
#创建触发事件
self.exitAction = QAction(QIcon('exit.png'), '&Exit', self)
self.exitAction.setShortcut('Ctrl+Q')
self.exitAction.setStatusTip('Exit application')
self.exitAction.triggered.connect(qApp.quit)
self.indivChatA = QAction(QIcon('exit.png'), '开始聊天', self)
self.indivChatA .setShortcut("开始聊天")
self.groupChatA = QAction(QIcon('exit.png'), '创建一个群聊', self)
self.groupChatA .setShortcut("创建群聊")
self.eGroupChatA = QAction(QIcon('exit.png'), '开始加入一个群聊', self)
self.eGroupChatA .setShortcut("加入群聊")
self.aGroupChatA = QAction(QIcon('exit.png'), '添加一个群聊', self)
self.aGroupChatA .setShortcut("添加群聊")
self.upFileA = QAction(QIcon('exit.png'), '上传文件', self)
self.upFileA.setShortcut("上传文件")
self.getHelpA = QAction(QIcon('exit.png'), '帮助', self)
self.getHelpA.setShortcut("帮助")
#添加菜单
self.chat =self.menuBar().addMenu("聊天")
self.indivChat =  self.chat.addMenu("选择个体聊天")
self.groupChat = self.chat.addMenu("创建群聊")
self.enterGC = self.chat.addMenu("加入群聊")
self.addGC = self.chat.addMenu("添加群聊")
self.up = self.menuBar().addMenu("上传文件")
self.help = self.menuBar().addMenu("帮助")
self.chooseUser = self.menuBar().addMenu("选择聊天对象")
self.quit = self.menuBar().addMenu("退出系统")
#为菜单添加Action
self.indivChat.addAction(self.indivChatA)   #添加个体聊天Action
self.groupChat.addAction(self.groupChatA)   #群聊Action
self.enterGC.addAction(self.eGroupChatA)    #加入群聊Action
self.addGC.addAction(self.aGroupChatA)      #添加群聊Action
self.up.addAction(self.upFileA)             #上传文件Action
self.help.addAction(self.getHelpA)          #帮助Action
#添加信号槽
self.inputConButton.clicked.connect(self.sendMessage)
self.inputCanBUtton.clicked.connect(self.sendMessage)
self.indivChatA.triggered.connect(lambda:self.emitChatSiganl("cp")) #个体聊天触发事件
self.groupChatA.triggered.connect(lambda:self.emitChatSiganl("cg")) #群聊触发事件
self.eGroupChatA.triggered.connect(lambda:self.emitChatSiganl("eg"))#加入一个群聊
self.aGroupChatA.triggered.connect(lambda:self.emitChatSiganl("ag"))#添加一个群聊
self.upFileA.triggered.connect(self.openFile)    #上传文件触发事件
self.getHelpA.triggered.connect(lambda:self.emitChatSiganl("h"))    #获取帮助触发事件
self.quit.addAction(self.exitAction)

def handle_click(self):
self.showText.setText("聊天内容")
if not self.isVisible():
self.show()
def emitChatSiganl(self,signal):

self.inputSigal.emit(signal)
print("lunched now")

def sendMessage(self):

message = str(self.inputText.toPlainText())
target = "max"
chat(target,message)
print(message)
print ("message has emited")
def setText(self,message):
print(message)
self.showText.setText(message)

print(message)
def openFile(self):
fileName, filetype = QFileDialog.getOpenFileName(self,
"选择文件路径",
"H:/",
"All Files (*);;Text Files (*.txt)")
print(fileName)
target = "max"
file = open(fileName)
print("文件打开成功")
data = file.read(1024)
print("文件读取成功")
sendFile(target,data)
print("文件发送成功")
print(fileName)
if __name__ == '__main__':
#创建页面实例对象
app = QApplication(sys.argv)
mp = MainPage()  #主页
lg = Login()     #登陆界面
re = Register()  #注册界面
cp = chatPage()  #聊天界面
myInputData = inputData()
# myGetData = getData()
mydata = getdata()
#将信号绑定到槽
mydata.getDataSignal.connect(cp.setText)
cp.inputSigal.connect(myInputData.setTarget)
mp.loginButton.clicked.connect(lg.handle_click)
mp.loginButton.clicked.connect(mp.hide)
mp.registerButton.clicked.connect(re.handle_click)
mp.registerButton.clicked.connect(mp.hide)
re.confirmButton.clicked.connect(re.sendData)
re.confirmButton.clicked.connect(cp.handle_click)
lg.cancelButton.clicked.connect(QCoreApplication.quit)
cp.sendMesSignal.connect(myInputData.setMessage)
#与服务器建立连接,获取链接对象
tcpCliSock.connect(ADDR)
print('Connected with server')
mydata.start()
sys.exit(app.exec_())


server.py(负责与客户端进行交互,存储聊天对象列表,返回请求)

1 import socketserver,json,time
2 import subprocess
3
4 connLst = []
5 groupLst = []
6 ##  代号 地址和端口 连接对象
7 #optype = {'ag':'group adding','cp':'chat with individual','cg':'chat with group'}
8 class Connector(object):   ##连接对象类
9     def __init__(self,account,password,addrPort,conObj):
10         self.account = account
11         self.password = password
12         self.addrPort = addrPort
13         self.conObj = conObj
14
15 class Group(object):#群组类
16     def __init__(self,groupname,groupOwner):
17         self.groupId = 'group'+str(len(groupLst)+1)
18         self.groupName = 'group'+groupname
19         self.groupOwner = groupOwner
20         self.createTime = time.time()
21         self.members=[groupOwner]
22
23 class MyServer(socketserver.BaseRequestHandler):
24
25     def handle(self):
26         print("got connection from",self.client_address)
27         userIn = False
28         global connLst
29         global groupLst
30         while not userIn:
31             conn = self.request
32             data = conn.recv(1024)
33             if not data:
34                 continue
35             dataobj = json.loads(data.decode('utf-8'))
36             #如果连接客户端发送过来的信息格式是一个列表且注册标识为False时进行用户注册或者登陆
37             ret = '0'
38             if type(dataobj) == list and not userIn:
39                 account = dataobj[0]
40                 password = dataobj[1]
41                 optype = dataobj[2]
42                 existuser = False
43                 if len(connLst) > 0:
44                     for obj in connLst:
45                         if obj.account == account:
46                             existuser = True
47                             if obj.password == password:
48                                 userIn = True
49                                 print('{} has logged in system({})'.format(account,self.client_address))
50                                 break
51                 if optype == 'login' and (not userIn or not existuser):
52                     ret = '1'
53                     print('{} failed to logged in system({})'.format(account, self.client_address))
54                 else:
55                     if existuser:
56                         ret = '1'
57                         print('{} failed to register({}),account existed!'.format(account, self.client_address))
58                     else:
59                         try:
60                             conObj = Connector(account,password,self.client_address,self.request)
61                             connLst.append(conObj)
62                             print('{} has registered to system({})'.format(account,self.client_address))
63                             userIn = True
64                         except:
65                             print('%s failed to register for exception!'%account)
66                             ret = '99'
67             #conn.sendall(ret.encode('utf-8'))
68             if ret == '0':
69                 break
70
71         while True:
72         #除登陆注册之外的请求的监听
73             conn = self.request
74             data = conn.recv(1024)
75             if not data:
76                 continue
77             print(data)
78             dataobj = data.decode('utf-8')
79             dataobj = json.loads(dataobj)
80             if dataobj['type'] == 'ag' and userIn:
81             #如果判断用户操作请求类型为添加群组则进行以下操作
82                 groupName = dataobj['groupName']
83                 groupObj = Group(groupName,self.request)
84                 groupLst.append(groupObj)
85                 conn.sendall('ag0'.encode('utf-8'))
86                 print('%s added'%groupName)
87                 continue
88
89             if dataobj['type'] == 'eg' and userIn:
90             #入群操作
91                 groupName = dataobj['groupName']
92                 ret = 'eg1'
93                 for group in groupLst:
94                     if groupName == group.groupName:
95                         group.members.append(self.request)
96                         print('{} added into {}'.format(self.client_address,groupName))
97                         ret = 'eg0'
98                         break
99                 conn.sendall(ret.encode('utf-8'))
100                 continue
101
102             #客户端将数据发给服务器端然后由服务器转发给目标客户端
103             print('connLst',connLst)
104             print('grouplst',groupLst)
105             if len(connLst) > 1:
106                 sendok = False
107                 if dataobj['type'] == 'cg':
108                 #群内广播(除发消息的人)
109                     print('group',data)
110                     for obj in groupLst:
111                         if obj.groupName == dataobj['to']:
112                             for user in obj.members:
113                                 if user != self.request:
114                                     user.sendall(data)
115                 if dataobj['type'] == 'cp':
116                 #个人信息发送
117                     for obj in connLst:
118                         if dataobj['to'] == obj.account:
119                             obj.conObj.sendall(data)
120                             sendok = True
121                     if sendok == False:
122                         print('no target valid!')
123                 if dataobj['type'] == 'f':
124                     for obj in connLst:
125                         if dataobj['to'] == obj.account:
126                             obj.conObj.sendall(data)
127                             sendok = True
128                     if sendok == False:
129                         print('no target valid!')
130             else:
131                 conn.sendall('-1'.encode('utf-8'))
132                 continue
133
134 if __name__ == '__main__':
135     server = socketserver.ThreadingTCPServer(('localhost',9998),MyServer)
136     print('waiting for connection...')
137     server.serve_forever()


client.py(与前端交互,并从后台sever获取数据)

1 from socket import *
2 import threading,sys,json,re
3 from PyQt5.QtCore import*
4 from PyQt5.QtWidgets import *
5 #引入json模块主要是为了数据的封装传输,re的话是做一些合法性的验证
6 HOST = 'localhost'
7 PORT=9998
8 BUFSIZE = 1024  ##缓冲区大小  1K
9 ADDR = (HOST,PORT)
10 myre = r"^[_a-zA-Z]\w{0,}"
11 tcpCliSock = socket(AF_INET,SOCK_STREAM)
12 #创建一个socket连接
13 userAccount = None
14 #用户登录标志,也用来记录登录的用户名称
15 def registerAndSend(list):
16 #用户注册函数
17     print("""
18     Glad to have you a member of us!
19     """)
20     accout = list[0]
21     # if not re.findall(myre, accout):
22     #     print('Account illegal!')
23     #     return None
24     password1  = str(list[1])
25     password2 = str(list[2])
26     if not (password1 and password1.__eq__(password2)):
27         print("password1: %s" %password1)
28         print("password2: %s" %password2)
29         print('Password not illegal!')
30         return None
31     try:
32         global userAccount
33         userAccount = accout
34         regInfo = [accout,password1,'register']
35         datastr = json.dumps(regInfo)
36         tcpCliSock.send(datastr.encode('utf-8'))
37         #data = tcpCliSock.recv(BUFSIZE)
38         data = "1"
39         data = data.decode('utf-8')
40         if data == '0':
41            print('Success to register!')
42            return True
43         elif data == '1':
44             print('Failed to register, account existed!')
45             return False
46         else:
47             print('Failed for exceptions!')
48             return False
49     except Exception as e:
50         print(e)
51
52 def loginAndSend(list):
53 #用户登录函数
54     print("""
55     Welcome to login in!
56     """)
57     accout = list[0]
58     if not re.findall(myre, accout):
59         print('Account illegal!')
60         return None
61     password = list[1]
62     if not password:
63         print('Password illegal!')
64         return None
65     global userAccount
66     userAccount = accout
67     loginInfo = [accout, password,'login']
68     datastr = json.dumps(loginInfo)
69     tcpCliSock.send(datastr.encode('utf-8'))
70     data = tcpCliSock.recv(BUFSIZE)
71     if data == '0':
72         print('Success to login!')
73         return True
74     else:
75         print('Failed to login in(user not exist or username not match the password)!')
76         return False
77
78 def chat(target,msg):
79 #进入聊天(群聊和点对点聊天可以选择)
80         print('{} -> {}: '.format(userAccount,target))
81         print("I am chating now inside the chat function")
82         if len(msg) > 0 and not msg in 'qQ':
83             if 'group' in target:
84                 optype = 'cg'
85             else:
86                 optype = 'cp'
87
88             dataObj = {'type': optype, 'to': target, 'msg': msg, 'froms': userAccount}
89             datastr = json.dumps(dataObj)
90             tcpCliSock.send(datastr.encode('utf-8'))
91 def sendFile(target,file):
92     print("a file send")
93     dataObj = {'type': "f", 'to': target, "file":file,'froms': userAccount}
94     print(dataObj["type"])
95     datastr = json.dumps(dataObj)
96     tcpCliSock.send(datastr.encode('utf-8'))
97     print("a file send")
98
99
100 class inputData(threading.Thread):
101     message = ""
102     targe = ""
103     def setMessage(self,msg):
104         global message
105         message = msg
106         print(message)
107         return message
108     def setTarget(self,tgt):
109         global target
110         targe = tgt
111         print(targe)
112         return targe
113     def run(self):
114         global targe,message
115         print(targe)
116         print(message)
117
118
119 class getdata(QThread):
120 #接收数据线程
121     getDataSignal = pyqtSignal(str)
122     def run(self):
123         while True:
124
125
126               data = tcpCliSock.recv(BUFSIZE).decode('utf-8')
127               dataObj = json.loads(data)
128               if dataObj['type'] == 'cp':
129                  newStr = str('{} -> : {}'.format(dataObj['froms'], dataObj['msg']))
130                  print(newStr)
131                  self.getDataSignal.emit(newStr)
132               elif dataObj['type'] == 'f':
133                  print("I got your file ")
134


前端界面展示:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: