import socket
import threading
import json # json.dumps(some)打包 json.loads(some)解包
import tkinter
import tkinter.messagebox
from tkinter.scrolledtext import ScrolledText # 导入多行文本框用到的包
IP = ''
PORT = ''
user = ''
listbox1 = '' # 用于显示在线用户的列表框
ii = 0 # 用于判断是开还是关闭列表框
users = [] # 在线用户列表
chat = '【群发】' # 聊天对象, 默认为群聊
# 登陆窗口
loginRoot = tkinter.Tk()
loginRoot.title('聊天室')
loginRoot['height'] = 110
loginRoot['width'] = 270
loginRoot.resizable(0, 0) # 限制窗口大小
IP1 = tkinter.StringVar()
IP1.set('127.0.0.1:8888') # 默认显示的ip和端口
User = tkinter.StringVar()
User.set('')
# 服务器标签
labelIP = tkinter.Label(loginRoot, text='地址:端口')
labelIP.place(x=20, y=10, width=100, height=20)
entryIP = tkinter.Entry(loginRoot, width=80, textvariable=IP1)
entryIP.place(x=120, y=10, width=130, height=20)
# 用户名标签
labelUser = tkinter.Label(loginRoot, text='昵称')
labelUser.place(x=30, y=40, width=80, height=20)
entryUser = tkinter.Entry(loginRoot, width=80, textvariable=User)
entryUser.place(x=120, y=40, width=130, height=20)
# 登录按钮
def login(*args):
global IP, PORT, user
IP, PORT = entryIP.get().split(':') # 获取IP和端口号
PORT = int(PORT) # 端口号需要为int类型
user = entryUser.get()
if not user:
tkinter.messagebox.showerror('温馨提示', message='请输入任意的用户名!')
else:
loginRoot.destroy() # 关闭窗口
loginRoot.bind('<Return>', login) # 回车绑定登录功能
but = tkinter.Button(loginRoot, text='登录', command=login)
but.place(x=100, y=70, width=70, height=30)
loginRoot.mainloop()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP, PORT))
if user:
s.send(user.encode()) # 发送用户名
else:
s.send('no'.encode()) # 没有输入用户名则标记no
# 如果没有用户名则将ip和端口号设置为用户名
addr = s.getsockname() # 获取客户端ip和端口号
addr = addr[0] + ':' + str(addr[1])
if user == '':
user = addr
# 聊天窗口
# 创建图形界面
root = tkinter.Tk()
root.title(user) # 窗口命名为用户名
root['height'] = 400
root['width'] = 580
root.resizable(0, 0) # 限制窗口大小
# 创建多行文本框
listbox = ScrolledText(root)
listbox.place(x=5, y=0, width=570, height=320)
# 文本框使用的字体颜色
listbox.tag_config('red', foreground='red')
listbox.tag_config('blue', foreground='blue')
listbox.tag_config('green', foreground='green')
listbox.tag_config('pink', foreground='pink')
listbox.insert(tkinter.END, '欢迎加入聊天室 !', 'blue')
# 表情功能代码部分
# 四个按钮, 使用全局变量, 方便创建和销毁
b1 = ''
b2 = ''
b3 = ''
b4 = ''
# 将图片打开存入变量中
p1 = tkinter.PhotoImage(file='./emoji/facepalm.png')
p2 = tkinter.PhotoImage(file='./emoji/smirk.png')
p3 = tkinter.PhotoImage(file='./emoji/concerned.png')
p4 = tkinter.PhotoImage(file='./emoji/smart.png')
# 用字典将标记与表情图片一一对应, 用于后面接收标记判断表情贴图
dic = {'aa**': p1, 'bb**': p2, 'cc**': p3, 'dd**': p4}
ee = 0 # 判断表情面板开关的标志
# 发送表情图标记的函数, 在按钮点击事件中调用
def mark(exp): # 参数是发的表情图标记, 发送后将按钮销毁
global ee
mes = exp + ':;' + user + ':;' + chat
s.send(mes.encode())
b1.destroy()
b2.destroy()
b3.destroy()
b4.destroy()
ee = 0
# 四个对应的函数
def bb1():
mark('aa**')
def bb2():
mark('bb**')
def bb3():
mark('cc**')
def bb4():
mark('dd**')
def express():
global b1, b2, b3, b4, ee
if ee == 0:
ee = 1
b1 = tkinter.Button(root, command=bb1, image=p1,
relief=tkinter.FLAT, bd=0)
b2 = tkinter.Button(root, command=bb2, image=p2,
relief=tkinter.FLAT, bd=0)
b3 = tkinter.Button(root, command=bb3, image=p3,
relief=tkinter.FLAT, bd=0)
b4 = tkinter.Button(root, command=bb4, image=p4,
relief=tkinter.FLAT, bd=0)
b1.place(x=5, y=248)
b2.place(x=75, y=248)
b3.place(x=145, y=248)
b4.place(x=215, y=248)
else:
ee = 0
b1.destroy()
b2.destroy()
b3.destroy()
b4.destroy()
# 创建表情按钮
eBut = tkinter.Button(root, text='表情', command=express)
eBut.place(x=5, y=320, width=60, height=30)
# 创建多行文本框, 显示在线用户
listbox1 = tkinter.Listbox(root)
listbox1.place(x=445, y=0, width=130, height=320)
def showUsers():
global listbox1, ii
if ii == 1:
listbox1.place(x=445, y=0, width=130, height=320)
ii = 0
else:
listbox1.place_forget() # 隐藏控件
ii = 1
# 查看在线用户按钮
button1 = tkinter.Button(root, text='用户列表', command=showUsers)
button1.place(x=485, y=320, width=90, height=30)
# 创建输入文本框和关联变量
a = tkinter.StringVar()
a.set('')
entry = tkinter.Entry(root, width=120, textvariable=a)
entry.place(x=5, y=350, width=570, height=40)
def send(*args):
# 没有添加的话发送信息时会提示没有聊天对象
users.append('【群发】')
print(chat)
if chat not in users:
tkinter.messagebox.showerror('温馨提示', message='没有聊天对象!')
return
if chat == user:
tkinter.messagebox.showerror('温馨提示', message='自己不能和自己进行对话!')
return
mes = entry.get() + ':;' + user + ':;' + chat # 添加聊天对象标记
s.send(mes.encode())
a.set('') # 发送后清空文本框
# 创建发送按钮
button = tkinter.Button(root, text='发送', command=send)
button.place(x=515, y=353, width=60, height=30)
root.bind('<Return>', send) # 绑定回车发送信息
# 私聊功能
def private(*args):
global chat
# 获取点击的索引然后得到内容(用户名)
indexs = listbox1.curselection()
index = indexs[0]
if index > 0:
chat = listbox1.get(index)
# 修改客户端名称
if chat == '【群发】':
root.title(user)
return
ti = user + ' --> ' + chat
root.title(ti)
# 在显示用户列表框上设置绑定事件
listbox1.bind('<ButtonRelease-1>', private)
# 用于时刻接收服务端发送的信息并打印
def recv():
global users
while True:
data = s.recv(1024)
data = data.decode()
# 没有捕获到异常则表示接收到的是在线用户列表
try:
data = json.loads(data)
users = data
listbox1.delete(0, tkinter.END) # 清空列表框
number = (' 在线用户数: ' + str(len(data)))
listbox1.insert(tkinter.END, number)
listbox1.itemconfig(tkinter.END, fg='green', bg="#f0f0ff")
listbox1.insert(tkinter.END, '【群发】')
listbox1.itemconfig(tkinter.END, fg='green')
for i in range(len(data)):
listbox1.insert(tkinter.END, (data[i]))
listbox1.itemconfig(tkinter.END, fg='green')
except:
data = data.split(':;')
data1 = data[0].strip() # 消息
data2 = data[1] # 发送信息的用户名
data3 = data[2] # 聊天对象
markk = data1.split(':')[1]
# 判断是不是图片
pic = markk.split('#')
# 判断是不是表情
# 如果字典里有则贴图
if (markk in dic) or pic[0] == '``':
data4 = '\n' + data2 + ':' # 例:名字-> \n名字:
if data3 == '【群发】':
if data2 == user: # 如果是自己则将则字体变为蓝色
奋斗奋斗再奋斗的ajie
- 粉丝: 1218
- 资源: 2589
最新资源
- c语言文本编辑器系统源码.zip
- 三菱FX3U与三菱变频器 modbus RTU通讯案例 器件:三菱FX3U PLC+FX3U 485BD,三菱E740变频器,昆仑通态触摸屏,威纶通 功能:采用485方式,modbus RTU协议
- 小学语文课外阅读教学途径及其影响因素探讨
- c语言五子棋源码.zip
- 计算机网络实验-深入解析DNS协议及其工具的应用
- c语言学生成绩管理系统.zip
- OC-Dialect线上多语言(多列表) 2.逻辑图对照代码运行
- 毕业实习与毕业设计总结
- 计算机仿真与分析课程设计指导:GUI界面设计及图像处理
- c语言学生成绩管理系统源码.zip
- c语言学生信息系统.zip
- 昆仑通态MCGS与三菱FX3U 485BD方式通讯案例功能:实现昆仑通态触摸屏与三菱FX3U的485BD板通过485方式进行连接,而PLC的编程口同时又能与电脑连接,进行程序下载监控 器件:三菱FX
- 酒店圣诞节活动策划安排
- 基于Wireshark与ENSP的企业级网络实验教程
- c语言支持自己创建迷宫并求解最短路径.zip
- 学习Matlab心得体会
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈