我在 Tkinter 中编写了一个简单的图像查看器 GUI,它在运行代码时首先要求用户选择一个包含图像的目录,然后图像显示在带有以下 3 个按钮的弹出窗口中:{{1} }、<<
和 >>
。前两个按钮沿相应方向滚动图像,而 Quit
按钮打开一个窗口,询问用户他/她是否希望“注释更多帧?”。如果答案是 Quit
,则 GUI 停止,但如果答案是 no
,我希望整个代码重新启动:关闭当前查看器窗口,再次询问用户(现在)不同的图像目录并使用新图像重新打开一个新的 Tkinter 图像查看器会话。
为了实现这一点,我首先将查看窗口定义为:
yes
正如所讨论的 here,root = 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()
我是否遗漏了一些明显的东西?非常感谢您的帮助和解答!