#! /usr/bin/python3.4
from tkinter import *
from tkinter.filedialog import askopenfilename
import time
from threading import Thread
import socket
import sys
import os.path
import process
#聊天实现类
class ChatClient(Thread):
#构造函数
def __init__(self):
Thread.__init__(self)
#提示信息输出
self.__info_event=None
#读取数据输出
self.__out_event=None
#创建套接字
self.clientSock=socket.socket()
#重用地址
self.clientSock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#返回提醒信息
#info事件
@property
def info_event(self):
return self.__info_event
@info_event.setter
def info_event(self,handler):
self.__info_event=handler
#info输出
def info(self,content):
if self.info_event!=None:
self.info_event(content)
#返回接收结果
#out事件
@property
def out_event(self):
return self.__out_event
@out_event.setter
def out_event(self,handler):
self.__out_event=handler
#out输出
def out(self,content):
if self.out_event!=None:
self.out_event(content)
#发送信息
def send(self,content):
if self.clientSock==None:
self.info("已经断开连接")
return -1
if type(content) is str:
content=content.encode()
elif type(content) is bytes:
pass
else:
self.info("发送信息类型错误")
return -1
try:
self.clientSock.send(content)
#self.info("已经发送信息")
return 0
except:
self.info("丢失连接")
return -1
#接受信息
def recv(self):
recv_msg={}
if self.clientSock==None:
return
fileobj=self.clientSock.makefile("rb")
while True:
try:
line=fileobj.readline()
except:
return None
if not len(line):
return None
elif line==b"\r\n":
break
else:
#print(line)
key,value=line.decode().strip().split(": ")
recv_msg[key]=value
if "Length" in recv_msg:
length=int(recv_msg["Length"])
recv_msg["Content"]=b""
while length>0:
r=fileobj.read(min(1024,length))
length-=len(r)
recv_msg["Content"]+=r
fileobj.close()
elif "Count" in recv_msg:
count=int(recv_msg["Count"])
#print(count)
recv_msg["Content"]=b""
while count>0:
recv_msg["Content"]+=fileobj.readline()
count-=1
fileobj.close()
return recv_msg
def run(self):
while True:
recv_msg=self.recv()
if recv_msg==None:
break
self.out(recv_msg)
#连接chat服务器
def connserver(self,servername,serverport):
try:
self.clientSock.connect((servername,serverport))
#self.info("成功连接pchat服务器")
return 0
except BaseException as e:
self.info("连接pchat服务器失败")
return -1
#断开连接
def disconnserver(self):
if self.clientSock!=None:
self.clientSock.close()
self.clientSock=None
self.info("断开连接")
return 0
#主界面类
class MainWindow(Tk):
#构造函数
def __init__(self,name,pwd,chatwith=None):
Tk.__init__(self)
#用户名属性
self.username=name
self.password=pwd
self.chatwith=chatwith
self.init()
self.conn()
def conn(self,host="127.0.0.1",port=1234):
#初始化chatclient
self.chatclient=ChatClient()
#添加事件处理
self.chatclient.info_event=self.info
self.chatclient.out_event=self.out
#连接
r=self.chatclient.connserver(host,port)
#开始接收服务器发送的数据
self.chatclient.start()
return r
#属性用户名
@property
def username(self):
return self.__username
@username.setter
def username(self,name):
self.__username=name
@property
def password(self):
return self.__password
@password.setter
def password(self,pwd):
self.__password=pwd
#属性 聊天对象
@property
def chatwith(self):
return self.__chatwith
@chatwith.setter
def chatwith(self,name):
self.__chatwith=name
#初始化菜单
def init_menu(self):
menubar=Menu(self,bg="lightblue")
self["menu"]=menubar
sysmenu=Menu(menubar,bg="lightblue")
menubar.add_cascade(label="系统",menu=sysmenu)
#下拉菜单
sysmenu.add_command(label="配置",command=self.clientConfigure)
sysmenu.add_separator()
sysmenu.add_command(label="登陆",command=self.login)
sysmenu.add_command(label="注册",command=self.register)
sysmenu.add_command(label="注销",command=self.outlogin)
sysmenu.add_separator()
sysmenu.add_command(label="结束",command=self.destroy)
#设置标题
def setTitle(self,name):
self.title("【%s】PChat [%s]"%(self.username,name))
#界面初始化
def init(self):
self.setTitle(self.chatwith)
self.init_menu()
left_frame=Frame(self)
left_frame.pack(expand=YES,fill=BOTH,side=LEFT)
right_frame=Frame(self)
right_frame.pack(fill=Y,side=LEFT)
self.friends_list=Listbox(right_frame,bg="lightblue")
self.friends_list.pack(expand=YES,fill=BOTH)
self.friends_list.bind("",self.select_friend)
self.friend_entry=Entry(right_frame)
self.friend_entry.pack(fill=X)
self.flush_button=Button(right_frame,text="刷新",command=self.flush)
self.flush_button.pack(side=LEFT)
self.add_button=Button(right_frame,text="增加",command=self.add)
self.add_button.pack(side=LEFT)
self.delete_button=Button(right_frame,text="删除",command=self.delete)
self.delete_button.pack(side=LEFT)
text_frame=Frame(left_frame,bg="white")
text_frame.pack(expand=YES,fill=BOTH)
self.chatmessage_text=Text(text_frame,bg="lightblue")
self.chatmessage_text.pack(expand=YES,fill=BOTH,side=LEFT)
text_scroll_bar=Scrollbar(text_frame,command=self.chatmessage_text.yview,bg="lightblue")
text_scroll_bar.pack(fill=Y,side=RIGHT)
self.chatmessage_text.configure(yscrollcommand=text_scroll_bar.set)
self.chatmessage_text.tag_config("header",foreground="green",font=("Arial",15))
self.chatmessage_text.tag_config("information",foreground="red",font=("Arial",10))
self.chatmessage_text.tag_config("file",foreground="yellow",font=("Arial",18))
self.chatmessage_text.tag_config("body",foreground="gray",font=("Arial",18))
self.inputmessage_string=StringVar()
self.inputmessage_entry=Entry(left_frame,bg="lightblue",textvariable=self.inputmessage_string)
self.inputmessage_entry.pack(fill=X)
self.inputmessage_entry.bind("",self.send)
self.send_button=Button(left_frame,text="发送",command=self.send,bg="lightblue")
self.send_button.pack(side=LEFT)
self.send_file_button=Button(left_frame,text="发送文件",command=self.sendfile)
self.send_file_button.pack(side=LEFT)
self.bottom_frame=Frame(self)
self.bottom_frame.pack(side=TOP,fill=X)
#self.usersname_label=Label(self.bottom_frame,text="用户名:")
#self.usersname_label.pack(side=LEFT)
#添加关闭窗口的事件处理
self.protocol("WM_DELETE_WINDOW",self.destroy)
def select_friend(self,event=None):
if len(event.widget.curselection()):
chatwith=event.widget.get(event.widget.curselection()[0])
if chatwith!="":
self.chatwith=chatwith
self.setTitle(self.chatwith)