深圳住房和建设管理局官方网站/搜索关键词推荐
tkinter-TinUI-xml实战(9)crosschat客户端
- 引言
- 声明
- 文件结构
- 核心代码
- 服务端连接
- 登录界面
- 主页面
- 主文件
- 结语
引言
CrossChat(十字街)是一个线上匿名群聊平台,类似Hack.Chat
。
现在通过websocket简单地构建一个cc的客户端。有以下几点注意:
-
只提供代码和基础思路,不提供代码功能详解
-
仅作为学习使用,不具备应用功能
声明
本项目属于作者原创。借鉴了GitHub/TinUI上的tuxml.py
,翻版必究,但可以自行添加功能代码。
本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以。
文件结构
-
crosschat.py - 参考hackchat.py
-
crosschat客户端.pyw - 主文件
-
loadin.xml - 聊天区登录界面
-
main.xml - 主页面
核心代码
服务端连接
参考pypi上的hackchat包,建立websocket连接。crosschat.py。
import json
import threading
import time
import websocketclass CrossChat:"""A library to connect to https://cross.chat/"""def __init__(self, nick, channel="programming"):"""Connects to a channel on https://cross.chat.Keyword arguments:nick -- <str>; the nickname to use upon joining the channelchannel -- <str>; the channel to connect to on https://hack.chat/"""self.nick = nickself.channel = channelself.online_users = []self.on_message = []self.on_join = []self.on_leave = []self.ws = websocket.create_connection("wss://ws.crosst.chat:35197/")self._send_packet({"cmd": "join", "channel": channel, "nick": nick})threading.Thread(target = self._ping_thread).start()def send_message(self, msg):"""Sends a message on the channel."""self._send_packet({"cmd": "chat", "text": msg})def _send_packet(self, packet):"""Sends <packet> (<dict>) to https://cross.chat."""encoded = json.dumps(packet)self.ws.send(encoded)def run(self):"""Sends data to the callback functions."""while True:result = json.loads(self.ws.recv())if result["cmd"] == "chat" and not result["nick"] == self.nick:for handler in list(self.on_message):handler(self, result["text"], result["nick"])elif result["cmd"] == "onlineAdd":self.online_users.append(result["nick"])for handler in list(self.on_join):handler(self, result["nick"])elif result["cmd"] == "onlineRemove":self.online_users.remove(result["nick"])for handler in list(self.on_leave):handler(self, result["nick"])elif result["cmd"] == "onlineSet":for nick in result["nicks"]:self.online_users.append(nick)def _ping_thread(self):"""Retains the websocket connection."""while self.ws.connected:self._send_packet({"cmd": "ping"})time.sleep(60)
登录界面
其实很简单,就是输入房间号和昵称。loadin.xml。
<!--TinUIXml编辑器-->
<tinui><line y="15"><line><paragraph text="chat room id"></paragraph></line><line><paragraph text="nick name"></paragraph></line><back></back><line><entry width="210">roomide</entry></line><line><entry width="210">nicknamee</entry></line></line><line x="60">
<paragraph text=" "></paragraph><button2 text="清空" command='self.funcs["cleanover"]'></button2><paragraph text=" "></paragraph><button2 text="进入" command='self.funcs["login"]'></button2></line>
</tinui>
主页面
main.xml。
<!--TinUIXml UI界面布局-->
<!--TinUIXml UI界面布局-->
<tinui><line><line><ui width="650" height="460" scrollbar="True">content</ui></line><line><textbox width="650" height="180" scrollbar="True">textbox</textbox></line><line><paragraph text=" " width="1000"></paragraph><button2 text="发送文本(Ctrl+Enter)" command='self.funcs["sendmsg"]'></button2></line><back></back><line><button2 text="使用须知📝" command='self.funcs["aboutuse"]'></button2><button2 text="关于应用🔎" command='self.funcs["aboutccpy"]'></button2><button2 text="注意事项❗" command='self.funcs["warnccpy"]'></button2></line><line><link text="基于hack.chat开发" url="https://hack.chat/"></link></line><line><ui width="360" height="610">aboutui</ui></line></line>
</tinui>
主要的功能UI部分在左边,右边只是给出了可能的附加功能,因此在接下来的主文件中实际上是没有相应的功能代码片段的。
主文件
from tinui import *
from tkinter import Tk
import crosschat
import threadingdef endy():bbox=content.bbox('all')if bbox==None:return 0else:return bbox[-1]
def addhere(t):content.add_paragraph((645,endy()+5),fg='#b48ead',text=nickname,anchor='ne')content.add_paragraph((645,endy()+1),text=t,anchor='ne')
def addthere(t,s):content.add_paragraph((5,endy()+5),fg='#8fa1b3',text=s,anchor='nw')content.add_paragraph((5,endy()+1),text=t,anchor='nw')
def addinfo(t):...def sendmsg(*e):#context=textbox.get(1.0,'end')addhere(context)ccc.send_message(context)textbox.delete(1.0,'end')def aboutuse(*e):#...def aboutccpy(*e):#...def warnccpy(*e):#...def message_got(chat, message, sender):addthere(message,sender)root=Tk()
root.geometry('1100x700+5+5')
root.title('CrossChat客户端')u=BasicTinUI(root)# main ui
u.pack(fill='both',expand=True)
x=TinUIXml(u)
#in
x.funcs["sendmsg"] = sendmsg
x.funcs["aboutuse"] = aboutuse
x.funcs["aboutccpy"] = aboutccpy
x.funcs["warnccpy"] = warnccpy
#during
with open('main.xml',mode='r',encoding='utf-8') as f:xml=f.read()
x.loadxml(xml)
#out
#out
content = x.tags["content"][0]#ui - main content chat
textbox = x.tags["textbox"][0]#textbox - text to chat
aboutui = x.tags["aboutui"][0]#ui - about view of ccpyu.pack_forget()
#-----logu=BasicTinUI(root,width=400,height=300)# log ui
logu.pack()
lx=TinUIXml(logu)
#in
def cleanover(*e):#roomide.delete(0,'end')nicknamee.delete(0,'end')
def login(*e):#global ccc,nicknamelogu.pack_forget()roomid=roomide.get()nickname=nicknamee.get()ccc=crosschat.CrossChat(nickname,roomid)ccc.on_message += [message_got]u.pack(fill='both',expand=True)threading.Thread(target = ccc.run).start()
lx.funcs["cleanover"] = cleanover
lx.funcs["login"] = login
with open('loadin.xml',mode='r',encoding='utf-8') as f:xml=f.read()
lx.loadxml(xml)
#out
roomide = lx.tags["roomide"][0]#entry
nicknamee = lx.tags["nicknamee"][0]#entryroot.mainloop()
结语
现在已经完成了一个简单的CC客户端,其它功能可以通过CC提供的API实现。
🔆tkinter创新🔆