基于python实现的聊天室(客户端:二)tkinter的美化ttkbootstrap的滚动文本框ScrollText自动滚动到底部

前言

就是自己想用python做一个聊天室,然后看看socket库,websocket库,有点底层,然后也会用到协程的东西,不是很明白,一时间也不知道怎么写,然后就用了封装好的python-socketio来实现,做好了以后,跟同学用,被吐槽说滚轮不会自动下滑到底部,难用,于是我找天找地,在网上啥也没找到,经过自己一个多小时的摸索,终于找到了解决方法
想看看聊天室代码的话,可以到https://github.com/cgynb/a-flask-project/tree/guiChatroom看看。或者直接访问这个地址

http://81.70.180.118:12347/聊天呀.exe

是打包好的程序,服务端有在服务器上跑着了,可以直接使用的,但是低版本的windows运行可能会有点问题
请添加图片描述

需求

基本功能实现了之后,跟同学用,被吐槽说滚轮不会自动下滑到底部,难用,于是我找天找地,在网上啥也没找到,经过自己一个多小时的摸索,终于找到了解决方法

在聊天窗口和当前用户列表使用了ScrollText这个控件,但是当有新的消息的时候,我们希望能看到最新的消息,所以就需要我们设置将滚动条拉到底部,但是这样是很糟糕的体验,所以需要界面自动拉动
聊天信息窗口和用户列表的代码如下

        # 会话框
        self.msg_box = ScrolledText(self.window, width=100, height=22)
        self.msg_box.autohide_scrollbar()
        self.msg_box.place(x=30, y=60)

        # 用户列表
        self.user_list = ScrolledText(self.window, width=24, height=15)
        self.user_list.autohide_scrollbar()
        self.user_list.place(x=780, y=0)
        self.user_list.insert('end', '在线用户:')

解决过程

我查了一下源码,于是我吃惊的发现ScrollText这个控件竟然是Scrollbar和Text控件组合在一起的,所以我就想应该是在滚动条(Scrollbar),这个类应该是有一个方法可以调整的,找了半天,没找到。所以我就把目光放在了Text上,果然就是这样的

具体解决

根据官方文档引入ScrollText

from ttkbootstrap.scrolled import ScrolledText

然后Ctrl+鼠标左键,可以看到ScrollText源码,在__init__函数中会发现这样的初始化

        # setup text widget
        self._text = ttk.Text(self, padx=50, **kwargs)

然后Ctrl+鼠标左键单机Text

class Text(Widget, XView, YView):

我们会发现,这个Text类继承了YView这个类,还有XView,那么联想一下,可以猜到可能就是这个YView跟文本展现的位置有关,所以我们Ctrl+鼠标左键YView

class YView:
    """Mix-in class for querying and changing the vertical position
    of a widget's window."""

    def yview(self, *args):
        """Query and change the vertical position of the view."""
        res = self.tk.call(self._w, 'yview', *args)
        if not args:
            return self._getdoubles(res)

    def yview_moveto(self, fraction):
        """Adjusts the view in the window so that FRACTION of the
        total height of the canvas is off-screen to the top."""
        self.tk.call(self._w, 'yview', 'moveto', fraction)

    def yview_scroll(self, number, what):
        """Shift the y-view according to NUMBER which is measured in
        "units" or "pages" (WHAT)."""
        self.tk.call(self._w, 'yview', 'scroll', number, what)

用咱们悲伤的英文一看,诶,有个yview_moveto方法,这一看就是移动文本位置的方法呀

所以我展示消息的函数就是这么写的

    def show_msg(self, username, message):
        if message:
            self.msg_box.insert('end', '\n' + username + ':' + '\n   ' + message)
            self.msg_box.text.yview_moveto(1)

这边其实有个python基础的小细节,就是在ScrollText源码中可以发现,他那个类属性是这么写的

self._text = …

但是为什么在我的代码中是这样的呢

self.msg_box.text.yview_moveto(1)

于是我突然想到,是跟类属性有关的东西哦,所以查了一下,这个属性应该将前面的_,去掉

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
实现基于UDP的网络聊天室再用Tkinter显示,可以按照以下步骤进行: 1. 编写UDP聊天室的服务器和客户端程序,实现聊天信息的发送和接收。可以使用Python标准库中的socket模块来实现网络通信功能。 2. 在Tkinter中创建一个窗口,并添加需要的组件,如文本框、按钮等。可以使用Tkinter提供的组件库,比如Label、Button、Entry等。 3. 在Tkinter程序中处理用户的输入和网络数据的接收,将聊天信息显示在窗口中。可以使用Tkinter提供的事件处理机制来响应用户的操作,比如Button的command属性和Entry的bind方法。 4. 测试程序,检查是否能够正常地发送和接收聊天信息,并在Tkinter窗口中正确地显示。 下面是一个简单的示例代码,仅供参考: ```python import socket import threading import tkinter as tk # 创建UDP客户端 client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 设置服务器地址和端口号 SERVER_ADDRESS = ('localhost', 8888) # 创建Tkinter窗口和组件 root = tk.Tk() root.title('UDP聊天室') text = tk.Text(root) text.pack(fill=tk.BOTH, expand=True) input_frame = tk.Frame(root) input_frame.pack(side=tk.BOTTOM, fill=tk.X) input_text = tk.Entry(input_frame) input_text.pack(side=tk.LEFT, fill=tk.X, expand=True) send_button = tk.Button(input_frame, text='发送') send_button.pack(side=tk.RIGHT) # 处理发送按钮的点击事件 def send_message(event): message = input_text.get() if message: client_socket.sendto(message.encode(), SERVER_ADDRESS) input_text.delete(0, tk.END) send_button.bind('<Button-1>', send_message) # 处理接收消息的线程 def receive_message(): while True: data, address = client_socket.recvfrom(1024) message = data.decode() text.insert(tk.END, f'{address}: {message}\n') # 启动接收消息的线程 receive_thread = threading.Thread(target=receive_message) receive_thread.setDaemon(True) receive_thread.start() root.mainloop() # 关闭UDP客户端 client_socket.close() ``` 这个程序创建了一个UDP客户端,使用Tkinter创建了一个窗口和两个组件,一个是用于显示聊天信息的文本框,另一个是用于输入聊天信息的文本框和发送按钮。当用户点击发送按钮时,程序会将输入的消息发送到服务器,服务器将消息广播给所有客户端客户端接收到消息后将其显示在文本框中。 需要注意的是,UDP协议是不可靠的,可能会出现丢包、重复等问题,因此需要考虑一些错误处理和容错机制。另外,这个示例代码只是一个简单的实现,还有很多可以改进的地方,比如添加用户名、支持私聊等,需要根据实际需求进行改进。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gsxdcyy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值