构思
我在CSDN上看了一篇文章,叫做 “tkinter制作弹幕”。但这并不是真正意义上的弹幕,而仅仅是弹窗,同时如此多的窗口会可能让人感到不适。
因此,我想实现一个能够横向移动的窗口,实现真正的屏幕弹幕。
创建类
我们准备创建一个名为BalloonTk的类,不继承任何组件,而是在类里面创建可移动的窗口。
制定 init 函数
首选,弹幕肯定要有文字和颜色,那么 __init__() 中需要有 “text”,“fg”以及“bg”属性。
其次,为了体现弹幕特征,窗口应该是有一点透明的,所以属性中还得有 “alpha”属性,在这一个类中,我们默认窗口是不透明的。
所以BalloonTk的框架为:
from tkinter import Tk,Label#...
#...
class BalloonTk():#使用tk窗口来实现弹窗效果,目前是覆盖整个屏幕
def __init__(self,text,fg='',bg='',alpha=1):
self.fg=fg
self.bg=bg
self.text=text
self.alpha=alpha
移动
这篇文章主要讲思路,所以我们只实现弹幕从右往左水平移动,跟正常的视频弹幕一样。
窗口的起始位置就是屏幕的宽度,但是我们不可能让每一弹幕都从同一个位置出来,因此我们在显示窗口的时候需要接受不同的起始高度。
#移动函数
def show(self,heigh):#移动模块
alpha=self.alpha#一般是不建议像这样使用self的,这里是为了测试方便
fg=self.fg
bg=self.bg
text=self.text
a=Tk()
a.overrideredirect(True)#取消标题栏
a.bind('<Button-1>',self.destroy)#点击删除
a.attributes('-alpha',alpha)
a.attributes('-topmost',True)
self.a=a
word=Label(a,text=text,font=('宋体',13),fg=fg,bg=bg).pack(fill='both')
for i in range(0,a.winfo_screenwidth(),2)[::-1]:
try:#如果被点击删除,则退出线程
a.update()
a.geometry('+'+str(i)+'+'+str(heigh))
slp(0.03)
except:
return
a.destroy()
为什么这里面的注释中有“点击退出”和“退出线程”,接下来会作解释
退出
如果还是像开头那一篇文章,需要用到很多弹幕,如果窗口迟迟不消失,也会让人反感。
那么除了等待窗口运动到屏幕后自动销毁,还有什么快捷的销毁方法呢?显然,当我们迫切地想让弹幕消失,一般都会使用鼠标点击,因此就有了窗口绑定鼠标单击的设计了。
即
class BalloonTk:
#...
def destroy(self,event):
self.a.destroy()
启动
当我们迫不及待地要使用 BalloonTk(…).show(…) 时,会发现如果前面的弹幕没有运行完或被点击销毁,那么后面一个弹幕就不会出现。此时,多线程的设计也由此而出。
多线程
我们的类是一个窗口,使用多线程不会影响或修改其它主线程的东西,所以可以放心使用。现在建立一个 start 函数。
#from threading import Thread
def start(self,nobg=False):
Thread(target=lambda:self.show(heigh,nobg)).start()
无背景
视频弹幕一般是没有底色的,所以可以将 __init__ 中的bg更改为透明色,这个改动会在 show 函数中体现。
def show(self,nobg=False):#默认不透明
#...
if nobg==True:
a.attributes('-transparentcolor',bg)
#...
让我们来看一下有背景色弹幕的效果(无背景色弹幕在复杂颜色背景下不清楚,而且也很难点击销毁)
Tin知识库
完整代码
class BalloonTk():#使用tk窗口来实现弹窗效果,目前是覆盖整个屏幕
def __init__(self,text,fg='',bg='',alpha=1):
self.fg=fg
self.bg=bg
self.text=text
self.alpha=alpha
def destroy(self,event):#点击关闭
self.a.destroy()
def show(self,heigh,nobg=False):#移动模块
alpha=self.alpha
fg=self.fg
bg=self.bg
text=self.text
a=Tk()
a.bind('<Button-1>',self.destroy)#点击删除
a.overrideredirect(True)
a.attributes('-alpha',alpha)
a.attributes('-topmost',True)
self.a=a
word=Label(a,text=text,font=('宋体',13),fg=fg,bg=bg).pack(fill='both')
if nobg==True:
a.attributes('-transparentcolor',bg)
for i in range(0,a.winfo_screenwidth(),2)[::-1]:
try:#如果被点击删除,则退出线程
a.update()
a.geometry('+'+str(i)+'+'+str(heigh))
slp(0.03)
except:
return
a.destroy()
def start(self,heigh,nobg=False):#多线程启动弹幕
Thread(target=lambda:self.show(heigh,nobg)).start()
TinReader可移动工具栏
写在最后
tkinter的功能实际上还算是比较丰富的,有一定的拓展性。
tkinter实现弹幕,可以继续改进,如:添加背景图片,多方向移动等。
☀tkinter创新☀