python制作局域网聊天软件(微信高仿)——机房课必备(含下载教程)

我将使用python来制作一款用于局域网内部的聊天软件,名为Lan Chat(局域网聊天),高度仿照微信界面、控件布局、创建大小、颜色、登录窗口等,同时含有许多功能用于管理

你可以使用这款软件在内部进行聊天,发送文字、表情、上传文件、下载文件(暂时无法使用)、私信,这是都是基本功能,还有部分管理员才能使用的功能,如:设置公告、禁言、踢人、发送弹窗、添加黑名单等,此外还有一个最顶尖的身份,那就是服主。

服主用于最高权限,也是用于功能最多的用户,如:远程控制、授权身份、文件管理等。服主还可以进入开发者后台对服务器进行设置等操作

注:只有服务器的创建者才能是服主

需要更多功能尽情评论

废话不多说我们先来看下效果

这是登录窗口

登录窗口高度还原原版微信

加载界面

主要聊天窗口

这里就是我们主要的聊天窗口了,高度还原微信。右侧中间是Lan Chan的LOGO(网络上找的),左侧就是我们的聊天对象了,默认情况下我们都会含有一个全服的群聊,也就是所有人都会在这个群聊里面,在Lan Chat中,群聊是使用一对中文中括号括起来的,图标也会显示群聊图标

当我们在左侧单单击任意对象即可进入到该对象的对话窗口中,在右下方会显示你的身份,新用户默认都是普通用户,普通用户仅支持聊天等基本功能,你可以向服主索要更高的身份

我相信你们都用过微信,那么我就不再介绍了,更多功能可以自己下载去摸索哦

下面我就要开始讲解源码了

在源码中含有多个配置文件,我主要讲解头文件

import socket,sys,re,os,struct,hashlib,TKDnD,time,random,signal
import tkinter as tk
from datetime import *
from tkinter.ttk import *
from tkinter import messagebox,scrolledtext,simpledialog,filedialog
from DataManagement import DataManagement
from CServer import CServer
import threading
import pyperclip

import multiprocessing
from multiprocessing import Process

#第三方库
import ToolTip
from pynput import keyboard
from win11toast import toast
from SysTrayIcon import SysTrayIcon

首先这是我们需要导入的库,其中导入了其他第三方库

if __name__ == "__main__":
    
    LogonWindows = tk.Tk()
    LogonWindows.title("Lan Chat")
    LogonWindows["background"] = "#FFFFFF"

    #获取屏幕分辨率
    screen_width = LogonWindows.winfo_screenwidth()
    screen_height = LogonWindows.winfo_screenheight()

    def CloseProcess():
        #关闭进程
        pid = os.getpid() # 获取当前进程的PID
        os.kill(pid, signal.SIGTERM) # 主动结束指定ID的程序运行

    LogonWindows_size = "280x350+%d+%d" % (screen_width / 2 - 280 /2, screen_height / 2 - 350 / 2)
    LogonWindows.tk.call("wm", "iconphoto", LogonWindows._w, tk.PhotoImage(file="icon\\LanChat.png"))
    LogonWindows.protocol("WM_DELETE_WINDOW", CloseProcess)
    LogonWindows.geometry(LogonWindows_size)
    LogonWindows.resizable(0,0)

    #布局
    HeadIcon = tk.PhotoImage(file="icon\\Head.png")
    Head = tk.Label(LogonWindows, image=HeadIcon, cursor="hand2")
    Head.place(x=100,y=50)

    #名字
    Name = tk.Label(LogonWindows, text=NativeIP, font=("微软雅黑",15), bg="#FFFFFF")
    Name.place(x=138,y=178,anchor="s")

    def EnterLanChatBG_Enter(event):
        """进入时的背景色"""
        EnterLanChat["bg"] = "#38CD7F"

    def EnterLanChatBG_Leave(event):
        """离开时的背景色"""
        EnterLanChat["bg"] = "#07C160"

    def Logon_LanChat():
        """登录LanChat"""
        if EnterIng == True:
            if Entering["text"] == "正在进入 .":
                Entering["text"] = "正在进入 .."
            elif Entering["text"] == "正在进入 ..":
                Entering["text"] = "正在进入 ..."
            else:
                Entering["text"] = "正在进入 ."

            LogonWindows.after(250,Logon_LanChat)

        elif EnterIng == "已登录":
            return

        elif EnterIng == "连接失败":
            FailureReason["text"] = "无法连接到服务器,请检查网络连接和防火墙设置"
            FailureReason.place(x=0,y=330)

            Entering.place(y=1770)
            Name.place(y=178)
            EnterLanChat.place(y=240)

        else:
            FailureReason["text"] = EnterIng
            FailureReason.place(x=0,y=330)

            Entering.place(y=1770)
            Name.place(y=178)
            EnterLanChat.place(y=240)

    def CallLogon():
        """登录时的中转函数"""
        global EnterIng

        EnterIng = True

        Entering.place(y=177)
        Name.place(y=1780)
        EnterLanChat.place(y=2400)
        FailureReason.place(y=350)
        Logon_LanChat()

        Logon() #进入聊天窗口


    #按钮
    EnterLanChat = tk.Label(LogonWindows, text="进入Lan Chat", font=("微软雅黑",11), bg="#07C160", fg="#DAF6E7", cursor="hand2")
    EnterLanChat.place(x=50,y=240,width=180,height=35)

    #正在进入
    Entering = tk.Label(LogonWindows, text="正在进入 .", font=("微软雅黑",11), fg="#1DC66E", bg="#FFFFFF")
    Entering.place(x=138,y=1770,anchor="s")

    #失败原因
    FailureReason = tk.Label(LogonWindows, text="无法连接到服务器,请检查网络连接和防火墙设置", bg="#FFFFFF", fg="red")
    FailureReason.place(x=0,y=350)

    EnterLanChat.bind("<Enter>", EnterLanChatBG_Enter)
    EnterLanChat.bind("<Leave>", EnterLanChatBG_Leave)
    EnterLanChat.bind("<ButtonRelease-1>", lambda event : threading.Thread(target = CallLogon).start())

    LogonWindows.mainloop()

这里就是我们登录窗口的代码

def Logon():
    """登录函数"""
    
    global c,ip,myname,loginTime,identity,SupremeIdentity,name_list,Change_Number,object_list
    global All_Objects,All_object_groups,EnterIng

##    print("正在连接...")


    #messagebox.showinfo("S",OldPID)

    
    c = socket.socket() #创建socket对象

    Connection_method = DataManagement.ReadData("Connect\\Connection method.json") #获取连接方式

    if Connection_method == "默认":
        
##        print("连接方式:默认")
        
        if Network_segment == "11.11.11.":
            host_number = ["11"]
            
        elif Network_segment == "10.103.250.":
            host_number = ["96","160","161"]

        elif Network_segment == "10.103.252.":

            host_number = ["160"]
            
        elif Network_segment == "10.103.253.":
            host_number = ["14","224","161","96"]
            
        elif Network_segment == "10.103.254.":
            host_number = ["32","33"]

        elif Network_segment == "192.168.32.":
            host_number = ["11"]
        
        else:
            host_number = ["32","161","96","16"]

        for host in host_number:
            ip = Network_segment + host
            
            try:
                c.connect((ip,port)) #连接服务器
            except:
                if host_number.index(host) == len(host_number)-1:
##                    print("无法连接到服务器,请查看连接设置或联系服主")
##                    connect_windows = tk.Tk()
##                    connect_windows.withdraw()
##                    messagebox.showerror("连接失败","无法连接到服务器\n请查看连接设置或联系服主")
                    EnterIng = "连接失败"
                else:
                    continue
            else:
                GUI().send_msg(c, NativeIP.encode("utf-8"))

                content = GUI().handle_client(c) #接收登录信息
                
                if content[0:4] == "登录成功":
##                    print("已登录服务器:%s"%ip)

                    loginTime = datetime.now().strftime(time_format) #记录登录时间

                    identity = (GUI().handle_client(c)).strip() #存放我的当前身份

                    SupremeIdentity = (GUI().handle_client(c)).strip() #存放我的最高身份

                    name_list = (GUI().handle_client(c)).strip() #在线列表

                    Change_Number = (GUI().handle_client(c)).strip() #修改昵称次数

                    #FILE_LIST = ((GUI().handle_client(c))).split("*") if GUI().handle_client(c) != None else " " #文件列表

                    name_list = name_list.split(",")

                    myname = content[4:]

                    object_list = name_list.copy()

                    object_list.remove(myname)

                    All_Objects = object_list.copy()

                    All_Objects.insert(0,"【全服】")

                    All_object_groups = All_Objects.copy()
                    
                    GUI().main()
                else:
##                    connect_windows = tk.Tk()
##                    connect_windows.withdraw()
##                    messagebox.showerror("登录失败",content) #显示登录失败信息
                    EnterIng = content
                break
    else:
##        print("连接方式:自定义")
        
        Server_IP = DataManagement.ReadData("Connect\\Server IP.json") #服务器IP地址

        Server_IP = Server_IP.split(",")

        for host in Server_IP:
            
            ip = host
            
            try:
                c.connect((ip,port)) #连接服务器
            except:
                if Server_IP.index(host) == len(Server_IP)-1:
##                    print("无法连接到服务器,请查看连接设置或联系服主")
##                    connect_windows = tk.Tk()
##                    connect_windows.withdraw()
##                    messagebox.showerror("连接失败","无法连接到服务器\n请查看连接设置或联系服主")
                    EnterIng = "连接失败"
                else:
                    continue
            else:
                GUI().send_msg(c, NativeIP.encode("utf-8"))
                    
                content = GUI().handle_client(c) #接收登录信息
                           
                if content[0:4] == "登录成功":
##                    print("已登录服务器:%s"%ip)

                    loginTime = datetime.now().strftime(time_format) #记录登录时间

                    identity = (GUI().handle_client(c)).strip() #存放我的当前身份

                    SupremeIdentity = (GUI().handle_client(c)).strip() #存放我的最高身份

                    name_list = (GUI().handle_client(c)).strip() #在线列表

                    Change_Number = (GUI().handle_client(c)).strip() #修改昵称次数

                    #FILE_LIST = ((GUI().handle_client(c))).split("*") if GUI().handle_client(c) != None else " " #文件列表

                    name_list = name_list.split(",")

                    myname = content[4:]

                    object_list = name_list.copy()

                    object_list.remove(content[4:])

                    All_Objects = object_list.copy()

                    All_Objects.insert(0,"【全服】")

                    All_object_groups = All_Objects.copy()
                    
                    GUI().main()
                    
                else:
##                    connect_windows = tk.Tk()
##                    connect_windows.withdraw()
##                    messagebox.showerror("登录失败",content) #显示登录失败信息
                    EnterIng = content
                break

这里就是登录的函数,主要用于判断你是否可以登录

下面就是整个聊天窗口的函数了
class GUI():
    """用户图形界面类"""
    screen_width, screen_height = 0, 0 #存放屏幕分辨率

    def __init__(s):
        s.SysTrayIcon = None  # 判断是否打开系统托盘图标

        s.emoji_name = [ file_name[:file_name.rfind(".")] for file_name in os.listdir("emoji") ] #使用列表推导式获取表情包文件夹内的表情文件名

        s.emoji_pictrue = [] #表情包的数组

        s.Emotion_button_array = [] #表情库按钮的数组

        s.MessageBox = [] #存放所有的消息控件

        s.MemberFrameBox = [] #存放成员列表框架

        s.MemberHandBox = [] #存放成员头像的控件

        s.MemberName = [] #存放成员列表的名字控件

        s.MessageTime = [] #存放成员列表的消息时间

        s.MemberSmallMessage = [] #存放成员列表预览消息的控件

        s.MemberLine1 = [] #存放成员列表用于布局的辅助线1

        s.MemberLine2 = [] #存放成员列表用于布局的辅助线2

        s.CurrentObject = "" #当前对象

        s.ContentRootFrame = [] #存放消息区的所有根框架

        s.MessageRootFrame = [] #存放消息区显示消息的所有根框架

        s.ContentCanvasFrame = [] #存放消息区画布的框架

        "初始化图片"
        s.HeadSculptureIcon = tk.PhotoImage(file="icon\\HeadSculpture.png")

        s.PersonalProfilePictureIcon = tk.PhotoImage(file="icon\\PersonalProfilePicture.png") #个人头像,在线成员列表显示的
        
        s.GroundIcon = tk.PhotoImage(file="icon\\Ground.png") #群聊头像,在线成员列表显示的

        s.LanChat_Icon = tk.PhotoImage(file="icon\\Lan Chat.png") #背景图标

        s.NoticeIcon = tk.PhotoImage(file="icon\\公告.png")

        s.SettingsIcon = tk.PhotoImage(file="icon\\设置及其他.png")

        s.emojiIcon = tk.PhotoImage(file="icon\\表情.png")

        s.UploadFilesIcon = tk.PhotoImage(file="icon\\上传文件.png")

        s.ChatIcon = tk.PhotoImage(file="icon\\聊天.png")

        s.CollectIcon = tk.PhotoImage(file="icon\\收藏.png")

        s.FileIcon = tk.PhotoImage(file="icon\\文件.png")

        s.CircleFriendsIcon = tk.PhotoImage(file="icon\\朋友圈.png")

        s.LockIcon = tk.PhotoImage(file="icon\\锁定.png")

        s.MoreIcon = tk.PhotoImage(file="icon\\更多.png")

    def send_msg(s, sock, msg):
        """发送消息"""
        # 计算消息长度
        msglen = len(msg)
        # 将消息长度编码为4个字节的二进制数据
        msglen_bytes = msglen.to_bytes(4, byteorder="little")
        # 发送消息长度
        sock.sendall(msglen_bytes)
        # 发送消息内容
        sock.sendall(msg)

    def recv_msg(s,sock):
        """接收信息"""
        # 先接收4个字节的消息长度
        raw_msglen = sock.recv(4)
        if not raw_msglen:
            return None
        # 将消息长度解码为整数
        msglen = int.from_bytes(raw_msglen, byteorder="little")
        # 接收实际的消息内容
        msg = b""
        while len(msg) < msglen:
            chunk = sock.recv((msglen - len(msg)))
            if not chunk:
                return None
            msg += chunk
        return msg

    def handle_client(s,conn):
        """处理消息"""
        # 接收消息
        data = s.recv_msg(conn)
        if not data:
            return
        # 处理消息
        message = data.decode()
        return message

    def main(s):
        global All_object_groups,EnterIng

        #窗口设置
        s.root = tk.Toplevel(LogonWindows)
        s.root.withdraw() #隐藏窗口,等待所有控件加载完毕
        s.root.protocol("WM_DELETE_WINDOW",lambda:s.Hidden_window()) #点击关闭窗口时,将窗口隐藏至托盘
        s.root.title("Lan Chat")
        

        #获取屏幕分辨率
        screen_width = s.root.winfo_screenwidth()
        screen_height = s.root.winfo_screenheight()

        window_size = "910x630+%d+%d"%(screen_width / 2 - 910 /2, screen_height / 2 - 630 / 2)
        s.root.tk.call("wm", "iconphoto", s.root._w, tk.PhotoImage(file="icon\\LanChat.png"))
        s.root.geometry(window_size)
        s.root.resizable(0,0)
        #s.root["background"] = "#F5F5F5"

        #根框架
        root_frame = tk.Frame(s.root, bg="#F5F5F5")
        root_frame.place(x=0,y=0,width=1215,height=630)

        "变量存储器---------------------------------------------------------------------------------------------------------"
        people_ID = tk.StringVar() #当前身份存储
        
        anonymous_values = tk.IntVar() #匿名存储器的值

        automatically_send_value = tk.IntVar() #自动发送存储器 True开启 False关闭

        CustomNicknameWordCount = tk.IntVar() #自定义的昵称字数

        AllowChatting = tk.IntVar() #允许成员变量存储
        AllowChatting.set(1) #默认值为1

        AllowLogin = tk.IntVar() #允许登录服务器存储
        AllowLogin.set(1) #默认值为1

        AutoDisplay = tk.IntVar() #自动显示最新消息
        AutoDisplay.set(1) #默认值为1

        #功能区数据存储
        DetailedInformationSwitch = tk.IntVar() #详细信息

        UploadFile_Switch = tk.IntVar() #上传文件

        DownloadFile_Switch = tk.IntVar() #下载文件

        ChangeNickname_Switch = tk.IntVar() #修改昵称

        GroupChatManagement_Switch = tk.IntVar() #群聊管理

        ModifyIdentity_Switch = tk.IntVar() #修改身份

        "初始化表情图片"
        for expression in range(0,len(s.emoji_name)-1):
            s.emoji_pictrue.append(tk.PhotoImage(file="emoji\\%s.png"%s.emoji_name[expression]))

        def Offline():
            """下线"""
            global EnterIng
            
            #下线通知
            Offline_notification = messagebox.askokcancel("退出登录","退出登录后将无法收到新消息,\n确定退出登录?",parent=s.root,default="cancel")
            if Offline_notification:
##                pid = os.getpid() # 获取当前进程的PID
##                os.kill(pid, signal.SIGTERM) # 主动结束指定ID的程序运行

                EnterIng = ""
                
                c.close() #关闭套接字
                s.root.destroy()

                Entering.place(y=1770)
                Name.place(y=178)
                EnterLanChat.place(y=240)

                LogonWindows.deiconify()
            else:
                return

由于这个函数多达3000多行,这里就展示一点点啦

软件我已经打包好放在我的超星(学习通)课程里面了,课程邀请码是:69346126,需要的可以进入我的课程前往资料里面下载啦,你们应该用超星(学习通)吧,不用也没关系,我来教你吧

如果你是手机的话直接在应用商店搜索“学习通”下载就可以了

如果你是网页版就在浏览器(随便一个,例如:Microsoft Edge)搜索URL(网址):https://i.chaoxing.com/

然后你就会进入登录界面

然后你需要登录或注册进入(注册不用我说了吧,应该都会)

进来后点击右上角的“输入邀请码”

接着输入邀请码:14115314,点击确定,然后点击加入课程就可以啦

回到主页面(我学的课)刷新一下,就会新增一个课程,点击进入,在左侧找到资料,第一个Lan Chat(局域网聊天)就是这款软件啦,直接下载就可以了,含有服务器和客户端,你需要把客户端给其他人安装再登录你的服务器就可以进行聊天了,有什么待改进或者BUG或者需要添加新功能的都可以再左侧的讨论发表你的意见喔

我也会在课程里面分享更多资源哦

软件持续更新中,最新版见超星课程资料

源码出售,不免,需要私
  • 33
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值