Python tkinter如何定义图像变量

Python tkinter如何定义图像变量,python,image,tkinter,python-imaging-library,Python,Image,Tkinter,Python Imaging Library,我已经把自制的音乐播放器安装好并开始运行了。现在是时候添加一些从当前使用ffmpeg播放的歌曲中提取的专辑艺术作品了。我已经做了很多搜索,但不确定在tkinter中设置此项的最有效方法。粗糙的窗户模型: +================+ | | Current Artist: Best Band Ever | (No Artwork) | Current Album: Greatest Album Ever | |

我已经把自制的音乐播放器安装好并开始运行了。现在是时候添加一些从当前使用
ffmpeg
播放的歌曲中提取的专辑艺术作品了。我已经做了很多搜索,但不确定在tkinter中设置此项的最有效方法。粗糙的窗户模型:

+================+
|                |   Current Artist: Best Band Ever
|  (No Artwork)  |   Current Album:  Greatest Album Ever
|                |   Current Song:   Irresistible Tune
|                |   Play Progress:  99.9 seconds of: 999
+================+
窗口底部是按钮;关闭、暂停、上一个、下一个

当抓取窗口边框放大时,我希望图片的大小最大,因为初始尺寸是200x200,这很难看到

我的问题是:如何在TK标签字段中定义image变量?

我暂时将图像设置为TK字符串变量:

    ''' Artwork image spanning 4 rows '''
    self.current_song_artwork = tk.StringVar()
    tk.Label(master2, text="(No Artwork)", font=(None, MON_FONTSIZE)) \
             .grid(row=0, rowspan=4, column=0, sticky=tk.W)

注1:我看过这个问答:它使用:

img2 = ImageTk.PhotoImage(Image.open(path2))
panel.configure(image=img2)
panel.image = img2
这似乎是唯一的选择

注2:第一次打开顶层窗口时,没有歌曲播放,也没有图像可供艺术品显示。需要某种占位符吗

注3:接下来,我想用音乐可视化工具(按比例缩小)、滚动歌词或滚动维基百科的传记来替换艺术作品。因此,采用稳健的设计进行未来验证在今天是有意义的

注意4:这只是我的第二个Python/Tkinter程序,下面的大部分代码都是从第一个程序复制和粘贴的。第一个主要是从堆栈溢出复制和粘贴代码。任何关于减少代码行或提高效率的提示都将不胜感激


TL;博士 完整的(不是很令人兴奋的代码)是:

def play_项目(自身):
''在listbox.selection()中播放一首或多首歌曲
“关闭”、“下一步”、“上一步”和“暂停”按钮
选择可能是艺术家、专辑或随机歌曲。获取项目标记:
自动开始播放第一首歌曲,使用:
ffplay-nodisp-autoexit“/path/to/song.ext”
如果按下暂停按钮,将文本更改为“播放”并发出:
带有pgrep ffplay的PID,然后使用kill-s STOP挂起
如果按下播放按钮,将文本更改为“暂停”并发出:
使用pgrep ffplay进行PID,然后使用kill-s CONT恢复
'''
如果len(self.listbox.selection())==0:
#TODO:对话框“选择要播放的一首或多首歌曲”
返回
''使父按钮不可见,以便用户不尝试单击''
self.clear_按钮()
self.top2=tk.Toplevel()
self.top2\u处于活动状态=真
''将窗口放置在父窗口的左上角,带有面板填充''
xy=(self.toplevel.winfo_x()+PANEL_HGT\
self.toplevel.winfo_y()+PANEL_HGT)
self.top2.minsize(宽度=BTN_宽度*10,高度=面板高度*4)
self.top2.geometry('++%d++%d'(xy[0],xy[1]))
self.top2.title(“播放选定歌曲”)
self.top2.configure(background=“Gray”)
self.top2.columnconfigure(0,权重=1)
self.top2.rowconfigure(0,权重=1)
''创建主框架''
master2=tk.框架(self.top2,borderwidth=BTN\u BRD\u WID,relief=tk.脊)
master2.网格(粘性=tk.NSEW)
''跨越4行的艺术品图像''
self.current_song_artwork=tk.StringVar()
标签(master2,text=“(无插图)”,字体=(无,字体大小))\
.grid(行=0,行跨度=4,列=0,粘性=tk.W)
“当前艺术家”
self.current_song_artist=tk.StringVar()
标签(master2,text=“当前艺术家:”,font=(无,monfontsize))\
.grid(行=0,列=1,粘性=tk.W)
tk.Label(master2,text=”“,textvariable=self.current\u song\u艺人\
字体=(无,monfontsize)).grid(行=0,列=2\
粘性=tk.W)
''当前相册''
self.current_song_album=tk.StringVar()
标签(master2,text=“当前相册:”,font=(无,monfontsize))\
.grid(行=1,列=1,粘性=tk.W)
tk.Label(master2,text=”“,textvariable=self.current\u song\u相册\
字体=(无,monfontsize)).grid(行=1,列=2\
粘性=tk.W)
“当前歌曲”
self.current_song_path=“”
self.current_song_name=tk.StringVar()
标签(master2,text=“当前歌曲:”,font=(无,monfontsize))\
.grid(行=2,列=1,粘性=tk.W)
tk.Label(master2,text=”“,textvariable=self.current\u song\u name\
字体=(无,monfontsize)).grid(行=2,列=2\
粘性=tk.W)
“游戏进展”
self.current_progress=tk.StringVar()
标签(master2,text=“播放进度:”,font=(无,monfontsize))\
.grid(行=3,列=1,粘性=tk.W)
tk.Label(master2,text=”“,textvariable=self.current_progress\
字体=(无,monfontsize)).grid(行=3,列=2\
粘性=tk.W)
''按钮框''
frame3=tk.Frame(self.top2,bg=“Blue”,borderwidth=BTN\u BRD\u WID\
卸压=槽)
frame3.grid(行=2,列=0,粘性=tk.NSEW)
frame3.grid_rowconfigure(0,权重=1)
frame3.grid_columnconfigure(0,权重=0)
button=tk.button(框架3,文本=”✘ 闭合“,宽度=BTN_宽度\
命令=自我。播放(关闭)
网格(行=0,列=0,padx=2,粘性=tk.W)
“关闭按钮”
self.top2.bind(“,self.play\u close)
self.top2.协议(“WM\u删除\u窗口”,self.play\u关闭)
“暂停/播放按钮”
self.pp_state=“播放”
self.pp_play_text=”▶  播放“
self.pp\u暂停\u文本=”❚❚ 暂停“
self.pp\u按钮\u文本=self.pp\u暂停\u文本
self.pp_按钮=tk.按钮(第3帧,文本=self.pp_按钮文本\
宽度=BTN\U WID,命令=self.pp\u切换)
self.pp_按钮.grid(行=0,列=1,padx=2)
“下一步/上一步按钮”

#U+1f844首先,这是一个非常全面的问题。这将有助于你和未来的谷歌搜索

这是可行的,但有一个f
def play_items(self):
    ''' Play 1 or more songs in listbox.selection()
        "Close", "Next", "Prev" and "Pause" buttons
        
        Selection may be artist, album or random songs. Get item tag:

        Auto-starts playing first song with:
            ffplay -nodisp -autoexit "/path/to/song.ext"
        If Pause button pressed change text to "Play" and issue:
            PID with pgrep ffplay then use kill -s STOP <PID> to suspend
        If Play button pressed change text to "Pause" and issue:
            PID with pgrep ffplay then use kill -s CONT <PID> to resume

    '''

    if len(self.listbox.selection()) == 0 :
        # TODO: Dialog "Select one or more songs to play."
        return

    ''' Make parent buttons invisible so user doesn't try to click '''
    self.clear_buttons()

    self.top2 = tk.Toplevel()
    self.top2_is_active = True

    ''' Place Window top-left of parent window with PANEL_HGT padding '''
    xy = (self.toplevel.winfo_x() + PANEL_HGT, \
          self.toplevel.winfo_y() + PANEL_HGT)
    self.top2.minsize(width=BTN_WID * 10, height=PANEL_HGT * 4)
    self.top2.geometry('+%d+%d'%(xy[0], xy[1]))
    self.top2.title("Playing Selected Songs")
    self.top2.configure(background="Gray")
    self.top2.columnconfigure(0, weight=1)
    self.top2.rowconfigure(0, weight=1)

    ''' Create master frame '''
    master2 = tk.Frame(self.top2, borderwidth=BTN_BRD_WID, relief=tk.RIDGE)
    master2.grid(sticky=tk.NSEW)

    ''' Artwork image spanning 4 rows '''
    self.current_song_artwork = tk.StringVar()
    tk.Label(master2, text="(No Artwork)", font=(None, MON_FONTSIZE)) \
             .grid(row=0, rowspan=4, column=0, sticky=tk.W)

    ''' Current artist '''
    self.current_song_artist = tk.StringVar()
    tk.Label(master2, text="Current Artist:", font=(None, MON_FONTSIZE)) \
             .grid(row=0, column=1, sticky=tk.W)
    tk.Label(master2, text="", textvariable=self.current_song_artist, \
             font=(None, MON_FONTSIZE)).grid(row=0, column=2, \
                                             sticky=tk.W)
    ''' Current album '''
    self.current_song_album = tk.StringVar()
    tk.Label(master2, text="Current Album:", font=(None, MON_FONTSIZE)) \
             .grid(row=1, column=1, sticky=tk.W)
    tk.Label(master2, text="", textvariable=self.current_song_album, \
             font=(None, MON_FONTSIZE)).grid(row=1, column=2, \
                                             sticky=tk.W)
    ''' Current song '''
    self.current_song_path = ""
    self.current_song_name = tk.StringVar()
    tk.Label(master2, text="Current Song:", font=(None, MON_FONTSIZE)) \
             .grid(row=2, column=1, sticky=tk.W)
    tk.Label(master2, text="", textvariable=self.current_song_name, \
             font=(None, MON_FONTSIZE)).grid(row=2, column=2, \
                                             sticky=tk.W)
    ''' Progress of play '''
    self.current_progress = tk.StringVar()
    tk.Label(master2, text="Play Progress:", font=(None, MON_FONTSIZE)) \
             .grid(row=3, column=1, sticky=tk.W)
    tk.Label(master2, text="", textvariable=self.current_progress, \
             font=(None, MON_FONTSIZE)).grid(row=3, column=2, \
                                             sticky=tk.W)

    ''' Frame for Buttons '''
    frame3 = tk.Frame(self.top2, bg="Blue", borderwidth=BTN_BRD_WID, \
                      relief=tk.GROOVE)
    frame3.grid(row=2, column=0, sticky=tk.NSEW)
    frame3.grid_rowconfigure(0, weight=1)
    frame3.grid_columnconfigure(0, weight=0)
    button = tk.Button(frame3, text="✘ Close", width=BTN_WID, \
                        command=self.play_close)
    button.grid(row=0, column=0, padx=2, sticky=tk.W)

    ''' Close Button '''
    self.top2.bind("<Escape>", self.play_close)
    self.top2.protocol("WM_DELETE_WINDOW", self.play_close)

    ''' Pause/Play Button '''
    self.pp_state = "Playing"     
    self.pp_play_text = "▶  Play"
    self.pp_pause_text = "❚❚ Pause"
    self.pp_button_text = self.pp_pause_text
    self.pp_button = tk.Button(frame3, text=self.pp_button_text, \
                        width=BTN_WID, command=self.pp_toggle)
    self.pp_button.grid(row=0, column=1, padx=2)

    ''' Next/Prev Button '''
    # U+1f844 First of all, what a really well put together comprehensive question. This will be helpful for you and future google-searchers.

This is doable, but there's a few gotchas to be careful of, namely saving to the class the image and its outer label. I've got a simple example here that will run, placing and displaying an image on a label.

import tkinter as tk
from PIL import Image,ImageTk

class Player:
    def __init__(self):
        self.root = tk.Tk()
        self.artwork_label = tk.Label()
        self.artwork_label.pack()
        self.img = ImageTk.PhotoImage(Image.open(path))
        self.artwork_label.configure(image=self.img)


path = ...
player = Player()