前言
就是自己想用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)
于是我突然想到,是跟类属性有关的东西哦,所以查了一下,这个属性应该将前面的_,去掉