tkinter-TinUI-xml实战(9)crosschat客户端

本文介绍了一个基于tkinter和TinUI的CrossChat客户端实现,它利用websocket连接到CrossChat服务器,提供了匿名群聊的功能。用户界面包括登录界面和主页面,允许用户输入房间号和昵称进行聊天。源码提供服务端连接、登录和消息处理的核心逻辑,同时提到了可扩展性,鼓励读者自行添加功能。
摘要由CSDN通过智能技术生成

引言

CrossChat(十字街)是一个线上匿名群聊平台,类似Hack.Chat

现在通过websocket简单地构建一个cc的客户端。有以下几点注意:

  1. 只提供代码和基础思路,不提供代码功能详解

  2. 仅作为学习使用,不具备应用功能


声明

本项目属于作者原创。借鉴了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 websocket

class 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 channel
        channel -- <str>; the channel to connect to on https://hack.chat/
        """
        self.nick = nick
        self.channel = channel
        self.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 threading

def endy():
    bbox=content.bbox('all')
    if bbox==None:
        return 0
    else:
        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 ccpy

u.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,nickname
    logu.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]#entry


root.mainloop()

结语

现在已经完成了一个简单的CC客户端,其它功能可以通过CC提供的API实现。

🔆tkinter创新🔆

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值