Tkinter <enter>和<leave>事件无法正常工作

时间:2017-08-25 08:50:03

标签: python tkinter

请事先原谅我的代码,但我只是为我的朋友做这个,自动填充一个GUI界面,其中包含歌曲信息,每首歌曲的频道信息,以及附加到歌曲上的图像等内容。现在我只是从Youtube上的播放列表和Soundcloud上的播放列表中搜集。我已经完成了所有这些工作,但是我对前端开发不熟悉,这使我处于一个可怕的位置,为他做出了不错的应用。我有很多想法,我可以做,但现在我只是创建按钮,每个歌曲标题作为文本。 Here is an image of my progress.我仍然需要找到一种方法将每个图像附加到on_enter事件的每个按钮,但这是以后的。如您所见,我有一个on_leave函数注释掉了。我每次离开按钮时都用它来删除self.image_window。问题是即使是极少量的鼠标移动也会导致窗口被删除并重新创建数十次。如何将其设置为静态,以便当我将鼠标悬停在按钮上时,它不会垃圾邮件创建/删除窗口?

谢谢!

from Tkinter import *
import json
import os
import webbrowser


class GUIPopulator(Frame):
    def __init__(self, parent):
        Frame.__init__(self)
        self.parent = parent
        self.configure(bg='PeachPuff2')
        self.columnconfigure(20, weight=1)
        self.rowconfigure(30, weight=1)
        self.curtab = None
        self.tabs = {}
        self.pack(fill=BOTH, expand=1, padx=5, pady=5)

        self.column = 0
        self.row = 0

    def on_enter(self, event):

        self.image_window = Toplevel(self)
        self.img_path = os.getcwd() + '/Rotating_earth_(large).gif'
        self.img = PhotoImage(file=self.img_path)

        #self.image_window.minsize(width=200, height=250)
        self.image_window.title("Preview")
        canvas = Canvas(self.image_window, width=200, height=200)
        canvas.pack()
        canvas.create_image(100, 100, image=self.img)
    #def on_leave(self, enter):



    def addTab(self, id):
        tabslen = len(self.tabs)

        tab = {}
        if self.row < 30:
            btn = Button(self, text=id,highlightbackground='PeachPuff2' ,command=lambda: self.raiseTab(id))

            btn.grid(row=self.row, column=self.column, sticky=W+E)

            btn.bind("<Enter>", self.on_enter)

            #btn.bind("<Leave>", self.on_leave)


            tab['id']=id
            tab['btn']=btn



            self.tabs[tabslen] = tab
            self.raiseTab(id)
            self.row +=1
        else:
            self.row = 0
            self.column +=1
            btn = Button(self, text=id,highlightbackground='PeachPuff2' ,command=lambda: self.raiseTab(id))

            btn.grid(row=self.row, column=self.column, sticky=W+E)

            tab['id']=id
            tab['btn']=btn

            self.tabs[tabslen] = tab
            self.raiseTab(id)


    def raiseTab(self, tabid):
        with open(os.getcwd() + '/../PlaylistListener/CurrentSongs.json') as current_songs:
            c_songs = json.load(current_songs)

        print(tabid)
        if self.curtab!= None and self.curtab != tabid and len(self.tabs)>1:
            try:
                #webbrowser.open(c_songs[tabid]['link'])
                webbrowser.open_new('http://youtube.com')
            except:
                pass



def main():
    root = Tk()
    root.title('Playlist Scraper')
    root.geometry("1920x1080+300+300")
    t = GUIPopulator(root)

    with open(os.getcwd() + '/../PlaylistListener/CurrentSongs.json') as current_songs:
        c_songs = json.load(current_songs)

    for song in c_songs:
            t.addTab(song)

    root.mainloop()

if __name__ == '__main__':
    main()

提供的JSON文件示例:

{
  "F\u00d8RD - Shadows (feat. Samsaruh)": {
    "page_title": "youtube",
    "link": "youtube.com/watch?v=CNiV6Pne50U&index=32&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "id": "CNiV6Pne50U",
    "channel": "youtube.com/watch?v=CNiV6Pne50U&index=32&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "image_path": [
      "http://i4.ytimg.com/vi/CNiV6Pne50U/hqdefault.jpg",
      "CNiV6Pne50U.jpg"
    ]
  },
  "Katelyn Tarver - You Don't Know (tof\u00fb remix)": {
    "page_title": "youtube",
    "link": "youtube.com/watch?v=7pPNv38JzD4&index=43&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "id": "7pPNv38JzD4",
    "channel": "youtube.com/watch?v=7pPNv38JzD4&index=43&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "image_path": [
      "http://i4.ytimg.com/vi/7pPNv38JzD4/hqdefault.jpg",
      "7pPNv38JzD4.jpg"
    ]
  },
  "Illenium - Crawl Outta Love (feat. Annika Wells)": {
    "page_title": "youtube",
    "link": "youtube.com/watch?v=GprXUDZrdT4&index=7&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "id": "GprXUDZrdT4",
    "channel": "youtube.com/watch?v=GprXUDZrdT4&index=7&list=PLkx04k4VGz1tH_pnRl_5xBU1BLE3PYuzd",
    "image_path": [
      "http://i4.ytimg.com/vi/GprXUDZrdT4/hqdefault.jpg",
      "GprXUDZrdT4.jpg"
    ]
  }
}

1 个答案:

答案 0 :(得分:0)

经过一些测试后,我想出了一些我认为你可以使用的代码或者你正在寻找的代码。

我更改了一些内容并添加了其他内容。

第一,我们需要为顶部窗口创建一个占位符,我们稍后可以在代码中使用它。因此,在__init__的{​​{1}}部分添加GUIPopulatior。我们很快就会讨论这个部分。

接下来我在self.image_window = None上创建了图像路径作为类属性,如果需要,可以稍后更新。

接下来,我向init添加了bind(),这有助于我们将init置于正确的位置,即使我们移动根窗口也是如此。所以我们也将self.image_window添加到self.parent.bind("<Configure>", self.move_me)部分。

接下来我们创建我们刚刚为其创建绑定的方法__init__。 它的编写方式只有在move_me不等于self.image_window时才会生效,这可以防止在使用None时出现任何错误但是我没有创建错误处理来处理在用户关闭顶层窗口后会发生什么。这并不难,但我想回答当前的主要问题。

以下是self.image_window方法:

move_me

接下来我们需要修改def move_me(self, event): if self.image_window != None: h = self.parent.winfo_height() # gets the height of the window in pixels w = self.parent.winfo_width() # gets the width of the window in pixels # gets the placement of the root window then uses height and width to # calculate where to place the window to keep it at the bottom right. self.image_window.geometry('+{}+{}'.format(self.parent.winfo_x() + w - 250, self.parent.winfo_y() + h - 250)) 方法以创建顶级窗口,如果类属性on_enter等于self.image_window,如果它不等于None那么我们可以使用if语句的else部分来更新图像。

以下是修改后的None方法:

on_enter

所有这些都说明你的代码还有一些其他问题需要解决,但是这个答案应该指向正确的方向。

以下是您需要替换的代码部分:

def on_enter(self, event):

    if self.image_window == None:
        self.image_window = Toplevel(self)
        #this keeps the toplevel window on top of the program
        self.image_window.attributes("-topmost", True)

        h = self.parent.winfo_height()
        w = self.parent.winfo_width()
        self.image_window.geometry('+{}+{}'.format(self.parent.winfo_x() + w - 250,
                                                   self.parent.winfo_y() + h - 250))
        self.img = PhotoImage(file=self.img_path)
        self.image_window.title("Preview")
        self.canvas = Canvas(self.image_window, width=200, height=200)
        self.canvas.pack()
        self.canv_image = self.canvas.create_image(100, 100, image=self.img)

    else:
        self.img = PhotoImage(file= self.img_path)
        self.canvas.itemconfig(self.canv_image, image = self.img)

有了这个:

class GUIPopulator(Frame):
    def __init__(self, parent):
        Frame.__init__(self)
        self.parent = parent
        self.configure(bg='PeachPuff2')
        self.columnconfigure(20, weight=1)
        self.rowconfigure(30, weight=1)
        self.curtab = None
        self.tabs = {}
        self.pack(fill=BOTH, expand=1, padx=5, pady=5)

        self.column = 0
        self.row = 0

    def on_enter(self, event):

        self.image_window = Toplevel(self)
        self.img_path = os.getcwd() + '/Rotating_earth_(large).gif'
        self.img = PhotoImage(file=self.img_path)

        #self.image_window.minsize(width=200, height=250)
        self.image_window.title("Preview")
        canvas = Canvas(self.image_window, width=200, height=200)
        canvas.pack()
        canvas.create_image(100, 100, image=self.img)
    #def on_leave(self, enter):