将 GIF 或图像添加到 tkinter 的 ScrolledText 小部件 或另一种与 BTTV 等动画表情聊天的实现

问题描述

我正在使用 Tkinter 在我的项目中创建聊天,例如抽搐。是否可以在消息中使用动画(不仅是)表情符号制作聊天小部件?

This is how it looks.

代码

def print_mess(self,mess):

    self.console.configure(state='normal')
    self.console.insert(END,mess.formated_time() + " ",'timesign')
    self.console.tag_config('timesign',foreground='#C0C0C0')
    self.console.insert(END,mess.username,mess.username)
    self.console.tag_config(mess.username,foreground=mess.usercolor)
    self.console.insert(END,": ",'mess')
    self.console.insert(END,mess.message + "\n",'mess')
    self.console.tag_config('mess',foreground='#FFFFFF')
    self.console.yview(END)  # autoscroll
    self.console.configure(state='disabled')

解决方法

有多种方法,一种方法是使用标签并使用 <head> <style> @import url('https://fonts.googleapis.com/css?family=Josefin+Sans:400,400i,600,600i'); html,body{ margin:0; height:120%; font-family: 'Josefin Sans',sans-serif;} a{ text-decoration:none } .header{ position:relative; overflow:hidden; display:flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; align-content: flex-start; height:50vw; min-height:600px; max-height:100%; min-width:300px; color:#eee; } .header:after{ content:""; width:100%; height:100%; position:absolute; bottom:0; left:0; z-index:-1; background: linear-gradient(to bottom,rgba(0,0.12) 40%,rgba(27,32,48,1) 100%); } .header:before{ content:""; width:100%; height:300%; position:absolute; top:0; left:0; -webkit-backface-visibility: hidden; -webkit-transform: translateZ(0); backface-visibility: hidden; scale(1.0,1.0); transform: translateZ(0); background:#1B2030 url(asthetic_Bg_Image1.jpg) 50% 0 no-repeat; background-size:100%; background-attachment:fixed; animation: grow 360s linear 10ms infinite; transition:all 0.4s ease-in-out; z-index:-2 } .header a{ color:#eee } .menu{ display:block; width:40px; height:30px; border:2px solid #fff; border-radius:3px; position:absolute; right:20px; top:20px; text-decoration:none } .menu:after{ content:""; display:block; width:20px; height:3px; background:#fff; position:absolute; margin:0 auto; top:5px; left:0; right:0; box-shadow:0 8px,0 16px } .logo{ border:2px solid #fff; border-radius:3px; text-decoration:none; display:inline-flex; align-items:center; align-content:center; position: relative; top: 1em; left: 12em; padding:0px 10px; font-weight:900; font-size:1.1em; line-height:1; box-sizing:border-box; height:40px } .sides,.info{ flex: 0 0 auto; width:50% } .info{ width:100%; padding:15% 10% 0 10%; text-align:center; text-shadow:0 2px 3px rgba(0,0.2) } .author{ display:inline-block; width:50px; height:50px; border-radius:50%; background:url(https://i.imgur.com/6DLCsZcb.jpg) center repeat; background-size:cover; box-shadow:0 2px 3px rgba(0,0.3); margin-bottom:3px } .info h4,.meta{ font-size:0.7em } .meta{ font-style:italic; } @keyframes grow{ 0% { transform: scale(1) translateY(0px)} 50% { transform: scale(1.2) translateY(-200px)} } .content{ padding:5% 10%; text-align:justify } button{ color:#333; height: 5px; border-radius:25px; text-decoration:none; display:inline-block; padding:5px 10px; font-weight:600 } .btn{ } .twtr{ margin-top:100px }.btn.twtr:after{content:"\1F426";padding-left:5px} .train2 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example1; animation-duration: 4s; right: 40em; top:10em; } @keyframes example1 { 0% { right: 0em; top: 10em;} 100% { right:40em; top:10em;} } .train3 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example3; animation-duration: 4s; right: 100%; /* changed */ animation-fill-mode: forwards; /* added to make it stay at the final position */ top: 15em; animation-delay: 2s; } @keyframes example3 { 0% { right: 100%; top:15em;} /* changed to put it completely left */ 100% { right: 40em; top:15em;} } .train4 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example4; animation-duration: 4s; left: 35em; top: 15em; animation-delay: 2s; } @keyframes example4{ 0% { left:0px; top:15em;} 100% { left:35em; top:15em;} } .train5 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example5; animation-duration: 4s; left: 35em; top: 21em; animation-delay: 6s; } @keyframes example5{ 0% { left:0px; top:21em;} 100% { left:35em; top:21em;} } .train6 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example6; animation-duration: 4s; right: 40em; top: 21em; animation-delay: 6s; } @keyframes example6{ 0% { right:0px; top:21em;} 100% { right:40em; top:21em;} } .train31 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example31; animation-duration: 4s; right: 40em; top: 27em; animation-delay: 10s; } @keyframes example31 { 0% { right:0px; top:27em;} 100% { right:40em; top:27em;} } .train41 { width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example41; animation-duration: 4s; left: 35em; top: 27em; animation-delay: 10s; } @keyframes example41{ 0% { left:0px; top:27em;} 100% { left:35em; top: 27 em;} } .train11{ width: 100px; height: 100px; background-color: red; position: absolute; animation-name: example11; animation-duration: 4s; right: 30em; top:32em; animation-delay: 14s; } @keyframes example11 { 0% { right:0px; top:32em;} 100% { right:30em; top:32em;} } .relax_tab{ height: 100vh; background-color: red; border-radius: 10px; margin: 5px; padding: 5px; } </style> </head> <body> <div class="header" style="text-align: center;"> <div class="sides" style="text-align: center;"> <a href="#" class="logo" style="text-align: center;">????????</a> </div> <div class="sides"> <a href="#" class="menu"> </a></div> <div class="info"> <h4><a href="#category"></a></h4> <a href="#relax_tab"> <button style="color:#333; border:2px solid; height: 37px; border-radius:25px; text-decoration:none; background-color: transparent ; color: white; display:inline-block; padding:5px 10px; font-weight:600" class="train2">Relax</button></a> <a href="#funny"> <button style="color:#333; border:2px solid; height: 37px; background-color: transparent ; color: white; border-radius:25px; text-decoration:none; display:inline-block; padding:5px 10px; font-weight:600" class="train3">Funny</button></a> <a href="#all_time"> <button style="color:#333; border:2px solid; height: 37px; border-radius:25px; text-decoration:none; background-color: transparent ; color: white; display:inline-block; padding:5px 10px; font-weight:600" class="train4">All Time fav.</button></a> <a href="#english"><button style="color:#333; border:2px solid; height: 37px; background-color: transparent ; color: white; border-radius:25px; text-decoration:none; display:inline-block; padding:5px 10px; font-weight:600" class="train5">English</button></a> <a href="#hindi"> <button style="color:#333; border:2px solid; height: 37px; background-color: transparent ; color: white; border-radius:25px; text-decoration:none; display:inline-block; background-color: transparent ; color: white; padding:5px 10px; font-weight:600" class="train6">Hindi</button></a> <a href="#chill"> <button style="color:#333; border:2px solid; height: 37px; background-color: transparent ; color: white; border-radius:25px; text-decoration:none; display:inline-block; padding:5px 10px; font-weight:600" class="train31">Chill</button></a> <a href="#sad"><button style="color:#333; border:2px solid; height: 37px; border-radius:25px; text-decoration:none; display:inline-block; background-color: transparent ; color: white; padding:5px 10px; font-weight:600" class="train41">Sad</button></a> <button style="color:#333; border:2px solid; height: 37px; background-color: transparent ; color: white; border-radius:25px; text-decoration:none; display:inline-block; padding:5px 10px; font-weight:600" class="train11">Suggestions</button> </body>

将其添加到文本小部件

示例:(拖放 gif。点击 gif 播放,修改它以满足您的需要)。

window_create()

另一种方法是使用 import tkinter as tk from PIL import Image,ImageTk import windnd class Text(tk.Text): def __init__(self,*args,**kwargs): super().__init__(*args,**kwargs) self.gif = {} self.index = 0 self.delay = 20 self.currentlyPlaying = None self.currentId = None def insert_gif(self,path): gif = GifMaker(path) label = tk.Label(image=gif.frames[0],bd=3) label.bind('<1>',lambda event: self.playGif(label)) self.window_create("end",window=label) self.gif[label] = gif self.playGif(label) def playGif(self,label): if self.currentlyPlaying is None: self.currentlyPlaying = label if self.currentlyPlaying != label: # makes sure only one gif is played at any time self.index = 0 self.currentlyPlaying.configure(image=self.gif[self.currentlyPlaying].frames[0]) self.currentlyPlaying = label self.after_cancel(self.currentId) self.index += 1 if self.index == self.gif[self.currentlyPlaying].n_frames-1: self.index = 0 self.currentlyPlaying.configure(image=self.gif[self.currentlyPlaying].frames[self.index]) if self.index != 0: self.currentId = self.after(self.delay,self.playGif,self.currentlyPlaying) class GifMaker: def __init__(self,path): self.path = path self.image = Image.open(path) self.n_frames = self.image.n_frames # number of frames self.frames = [] self.duration = 0 # total duration of the gif for x in range(self.n_frames): img = ImageTk.PhotoImage(self.image.copy()) self.duration += self.image.info['duration'] self.frames.append(img) self.image.seek(x) self.delay = self.duration//self.n_frames def dropped(file): text.insert_gif(file[0]) root = tk.Tk() text = Text() text.pack(fill='both',expand=True) windnd.hook_dropfiles(root,func=dropped) root.mainloop() 创建图像并使用 .image_create() 更新图像。 (推荐)

.image_configure()

(通过添加类似上述方法的条件,确保在任何情况下只播放一个 gif)

输出:

enter image description here