Tkinter:关闭当前窗口后打开一个新的图像查看器窗口

时间:2021-01-30 20:36:44

标签: python-3.x tkinter

我在 Tkinter 中编写了一个简单的图像查看器 GUI,它在运行代码时首先要求用户选择一个包含图像的目录,然后图像显示在带有以下 3 个按钮的弹出窗口中:{{1} }、<<>>。前两个按钮沿相应方向滚动图像,而 Quit 按钮打开一个窗口,询问用户他/她是否希望“注释更多帧?”。如果答案是 Quit,则 GUI 停止,但如果答案是 no,我希望整个代码重新启动:关闭当前查看器窗口,再次询问用户(现在)不同的图像目录并使用新图像重新打开一个新的 Tkinter 图像查看器会话。

为了实现这一点,我首先将查看窗口定义为:

yes

正如所讨论的 hereroot = Tk() root.withdraw() window = Toplevel(root) 并重新打开 destroy 似乎比原来的 Toplevel 更好。接下来,我将 root 按钮定义如下:

Quit

但这就是我的问题 - 我不确定用什么来替换 button_exit = Button(window, text="Quit", command=exit) def exit(event=None): global root # Quit dialog box answer = messagebox.askquestion(title="Quitting", message="Do you wish to annotate more frames?") if answer == 'yes': pass else: root.destroy() 。我很清楚我可以定义一个新窗口:

pass

但我不确定如何重新启动新的查看器会话。到目前为止,这是我的全部代码:

if answer == 'yes':
    window.destroy()
    window = Toplevel(root)

尽管这很丑陋,但我尝试只弹出整个代码块而不是 import os import re import glob from tkinter import Tk, Button, Label, DISABLED, NORMAL, filedialog, messagebox, Toplevel from PIL import ImageTk, Image #################################### DEFINITIONS #################################### def choose_frames(): # Define the frame directory frame_dir = filedialog.askdirectory(title="Choose a directory with frames to annotate") # Gather all frames in the passed "frame_dir" frames = glob.glob(os.path.join(frame_dir, "*.png")) frames.sort(key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)]) # Create a list of GUI-loading commands for each frame image_list = [] for frame in frames: image_list.append(ImageTk.PhotoImage(Image.open(frame))) return image_list def forward(event=None): # Update the image_number global image_number if image_number == len(image_list): # last image, disable forward button button_forward.configure(state=DISABLED) else: image_number += 1 # change image in label my_label.configure(image=image_list[image_number - 1]) # if no longer first frame, re-enable back button if image_number == 2: button_back.configure(state=NORMAL) def back(event=None): # Update the image_number global image_number if image_number == 1: # first image, disable back button button_back.configure(state=DISABLED) else: image_number -= 1 # change displayed image in label my_label.configure(image=image_list[image_number - 1]) # if no longer last image, re-enable forward button if image_number == (len(image_list) - 1): button_forward.configure(state=NORMAL) def exit(event=None): global window global root # Quit dialog box answer = messagebox.askquestion(title="Quitting", message="Do you wish to annotate more frames?") if answer == 'yes': pass else: root.destroy() ########################################################################################### # Initialize the GUI environment root = Tk() root.withdraw() window = Toplevel(root) window.configure(bg='black') window.title('Frame annotator') window.wm_protocol("WM_DELETE_WINDOW", root.destroy) # Gather a list of frames to visualize image_list = choose_frames() # Display the first image when opening the GUI ## Create the label object only once - when changing the displayed image, only reconfigure an existing object!!! image_number = 1 my_label = Label(window, image=image_list[image_number - 1]) my_label.grid(row=0, column=0, columnspan= 5, rowspan=50, padx=5, pady=5) # Define the GUI buttons button_back = Button(window, text="<<", command=back, state=DISABLED) button_forward = Button(window, text=">>", command=forward) button_exit = Button(window, text="Quit", command=exit) # Bind left/right arrow keyboard keys to back/forward buttons window.bind('<Left>', back) window.bind('<Right>', forward) # Place the GUI buttons in the GUI frame button_back.grid(row=48, column=0) button_forward.grid(row=48, column=3) button_exit.grid(row=48, column=4) window.mainloop()

pass

这确实导致旧窗口关闭,新窗口打开并要求用户输入新目录甚至加载第一帧,但在尝试循环浏览图像后,返回以下错误:

def exit(event=None):
    global window
    global root
    
    # Quit dialog box
    answer = messagebox.askquestion(title="Quitting", message="Do you wish to annotate more frames?")
    if answer == 'yes':
        window.destroy()
        window = Toplevel(root)
        window.configure(bg='black')
        window.title('Frame annotator')
        window.wm_protocol("WM_DELETE_WINDOW", root.destroy)

        # Gather a list of frames to visualize
        image_list = choose_frames()

        # Display the first image when opening the GUI
        ## Create the label object only once - when changing the displayed image, only reconfigure an existing object!!!
        image_number = 1 
        my_label = Label(window, image=image_list[image_number - 1])
        my_label.grid(row=0, column=0, columnspan= 5, rowspan=50, padx=5, pady=5)

        # Define the GUI buttons
        button_back = Button(window, text="<<", command=back, state=DISABLED)
        button_true = Button(window, text="TRUE")#, command=write_true)
        button_false = Button(window, text="FALSE")#, command=write_false)
        button_forward = Button(window, text=">>", command=forward)
        button_exit = Button(window, text="Quit", command=exit)

        # Bind left/right arrow keyboard keys to back/forward buttons
        window.bind('<Left>', back)
        window.bind('<Right>', forward)

        # Place the GUI buttons in the GUI frame
        button_back.grid(row=48, column=0)
        button_true.grid(row=48, column=1)
        button_false.grid(row=48, column=2)
        button_forward.grid(row=48, column=3)
        button_exit.grid(row=48, column=4)

        window.mainloop()

我是否遗漏了一些明显的东西?非常感谢您的帮助和解答!

0 个答案:

没有答案