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

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

  • 引言
  • 声明
  • 文件结构
  • 核心代码
    • 服务端连接
    • 登录界面
    • 主页面
    • 主文件
  • 结语

引言

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

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

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

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


声明

本项目属于作者原创。借鉴了GitHub/TinUI上的tuxml.py,翻版必究,但可以自行添加功能代码。

本项目使用的TinUI为我开源并维护在GitHub上的主文件——TinUI.py。当然,使用PYPI中下载安装的tinui也可以。


文件结构

tkinter-TinUI-xml实战(9)crosschat客户端_第1张图片

  • 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 -- ; the nickname to use upon joining the channel
        channel -- ; 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  () 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。


<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">roomideentry>
        line>
        <line>
            <entry width="210">nicknameeentry>
        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>

tkinter-TinUI-xml实战(9)crosschat客户端_第2张图片

主页面

main.xml。



<tinui>
    <line>
        <line>
            <ui width="650" height="460" scrollbar="True">contentui>
        line>
        <line>
            <textbox width="650" height="180" scrollbar="True">textboxtextbox>
        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">aboutuiui>
        line>
    line>
tinui>

tkinter-TinUI-xml实战(9)crosschat客户端_第3张图片

主要的功能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创新

你可能感兴趣的:(TinUI,tkinter实验,xml,tkinter,python,TinUI)