【发布时间】:2021-02-11 23:00:08
【问题描述】:
我遇到了与之前here 相同的问题,但那里的问题没有得到解答。本质上,我已经在tkinter 中编写了一个简单的 GUI,用箭头键列出定义的图像。我已经在 Jupyter 笔记本和 anaconda 环境中的 Ubuntu 18 上编写了代码,并且它在那里完全可以工作,但是当我尝试在 Windows 上以几乎相同的方式(在相同 anaconda 环境中的 Jupyter 笔记本中)运行相同的代码时,键绑定不再起作用。使用鼠标单击时,GUI 仍会打开并且所有按钮都可以使用,但键盘没有响应。这很奇怪,因为当我尝试一个简单的:
root = Tk()
def key_pressed(event):
print(event.char)
root.bind("<Key>", key_pressed)
root.mainloop()
程序返回按键(按下的字母,但对于箭头键,它返回一个空格 - 仍然可以清楚地识别按键,因为每次按下箭头键都会打印一个新的空格)。下面,找到完整的代码:
import os
import re
import glob
import pandas as pd
import numpy as np
from pathlib import Path
from tkinter import Tk, Button, Label, DISABLED, NORMAL, filedialog, messagebox
from PIL import ImageTk, Image
from moviepy.editor import VideoFileClip
#################################### GUI FUNCTIONS ####################################
def choose_frames(video_dir):
# Define the video to annotate
#initialdir = '/run/user/1000/gvfs/smb-share:server=krupix3.local,share=kage/Hinze/piCamera/'
video = filedialog.askopenfilename(initialdir = video_dir,
title = "Select video to annotate",
filetypes = ((".mp4 files","*.mp4"),("all files","*.*")))
# Set a list of frames to display
clip = VideoFileClip(video)
image_list = []
for frame in clip.iter_frames():
image_list.append(ImageTk.PhotoImage(master=root, image=Image.fromarray(frame)))
return image_list, video
def forward(event=None):
# Update the image_number
global image_number
if image_number == (len(image_list) - 1):
# 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])
# if no longer first frame, re-enable back button
if image_number == 1:
button_back.configure(state=NORMAL)
def back(event=None):
# Update the image_number
global image_number
if image_number == 0:
# 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])
# if no longer last image, re-enable forward button
if image_number == len(image_list):
button_forward.configure(state=NORMAL)
def exit():
# 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.configure(bg='black')
root.title('Frame annotator')
root.protocol("WM_DELETE_WINDOW", root.destroy) # Close the GUI if red "X" button is clicked in the GUI window
# Gather a list of frames to visualize
image_list, video = choose_frames(video_dir)
# 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 = 0
my_label = Label(root, image=image_list[image_number])
my_label.grid(row=0, column=0, columnspan= 12, rowspan=50, padx=5, pady=5)
# Define the GUI buttons
button_back = Button(root, text="<<", command=back, state=DISABLED)
button_forward = Button(root, text=">>", command=forward)
button_exit = Button(root, text="Quit", command=exit)
# Bind left/right arrow keyboard keys to back/forward buttons
root.bind('<Left>', back)
root.bind('<Right>', forward)
# Place the GUI buttons in the GUI frame
button_back.grid(row=48, column=4)
button_forward.grid(row=48, column=6)
button_exit.grid(row=48, column=11)
root.mainloop()
此外,我正在尝试通过 AnyDesk 在 Windows PC 上远程运行此代码。但是,我也尝试在另一台 Ubuntu 机器上通过 AnyDesk 远程运行代码,结果是一样的——代码在 Ubuntu 上运行良好。我想知道,对于 Windows,root.bind('<Left>', back) 和 root.bind('<Right>', back) 的命令是否不同?还是我还缺少其他东西?
非常感谢您的帮助!
【问题讨论】:
-
您是否尝试过将焦点强制到窗口上?仅当窗口具有键盘焦点时,键绑定才有效。否则代码很好 -
bind命令在不同平台上的工作方式没有区别。