终端菜单 - 向上 - 向下 - 输入 - 使用模块键盘
Menu for terminal - Up - Down - Enter - Using module keyboard
一周前刚开始使用 python。目前我正在尝试编写一个小程序 class,它在终端中创建一个菜单。这个想法是使用向上/向下键浏览菜单。您可以通过按 enter select 菜单项。我使用模块 "keyboard".
控制按下的键
为了使用我的 class,必须创建一个对象并通过方法 "add_menu" 添加菜单项。后面提到的方法有两个参数,第一个用于菜单项的名称,第二个用于传递一个函数,该函数将在按下回车时调用。
为了检查是否按下了某个键,我使用了模块键盘中的方法keyboard.on_press。如果按下某个键,方法 keyboard.on_press 将执行菜单对象的方法 handle_menu。 handle_menu 方法使用名为 "controller" 的列表来组织菜单项的 selection。基本上,它只是一个像 [0,0,1,0] 这样的列表。元素为 1 表示当前 selected 菜单项。
现在解决我的问题:我的菜单有一个菜单项 "Exit"。如果这是 selected 并按下回车键,我希望整个程序停止。因此,如果按下退出,属性 exit 将从 0 更改为 1。在我程序的 while 循环中,我总是检查 object.exit 是否为 != 1,否则程序应该结束。不知何故,这并不总是有效。如果我从一开始就立即向下滚动,而不在其他菜单项上按回车键,它就可以工作。但是,如果我在其他菜单项上多次按回车然后转到退出菜单项,程序不会再结束(或者只有当我按回车 10-20 次时)。感觉keyboard.on_press方法和while循环有时在后台解耦,运行异步?我不太明白这是怎么回事...
import keyboard #Using module keyboard
import os
class bcolors:
HEADER = '3[95m'
OKBLUE = '3[94m'
OKGREEN = '3[92m'
WARNING = '3[93m'
FAIL = '3[91m'
ENDC = '3[0m'
BOLD = '3[1m'
UNDERLINE = '3[4m'
def start_function():
print('Start works')
def save_function():
print('Save works')
def option_function():
print('Option works')
class c_menu:
def __init__ (self):
self.exit = 0
self.menu = []
self.functions = []
self.controller = []
def add_menu(self, menu, function):
self.menu.append(menu)
self.functions.append(function)
if len(self.controller) == 0:
self.controller.append(1)
else:
self.controller.append(0)
def start_menu(self):
os.system('cls' if os.name == 'nt' else 'clear')
for menu_item in range(len(self.menu)):
if self.controller[menu_item] == 1:
print(bcolors.WARNING + self.menu[menu_item])
else:
print(bcolors.OKBLUE + self.menu[menu_item])
def handle_menu(self, event):
os.system('cls' if os.name == 'nt' else 'clear')
if event.name == 'down':
if self.controller.index(1) != (len(self.controller) - 1):
self.controller.insert(0,0)
self.controller.pop()
elif event.name == 'up':
if self.controller.index(1) != 0:
self.controller.append(0)
self.controller.pop(0)
for menu_item in range(len(self.menu)): #printing all menu items with the right color
if self.controller[menu_item] == 1:
print(bcolors.WARNING + self.menu[menu_item])
else:
print(bcolors.OKBLUE + self.menu[menu_item])
if event.name == 'enter':
if self.functions[self.controller.index(1)] == 'exit':
self.exit = 1
return
self.functions[self.controller.index(1)]()
main_menu = c_menu()
main_menu.add_menu('Start', start_function)
main_menu.add_menu('Save', save_function)
main_menu.add_menu('Option', option_function)
main_menu.add_menu('Exit', 'exit')
main_menu.start_menu()
keyboard.on_press(main_menu.handle_menu)
while main_menu.exit != 1:
pass
我想我理解了这个问题。该程序实际上已正确结束,但是,最后按下的 "enter" 仍在某种缓冲区(或类似的东西)中,并且在程序结束后,终端命令 "python menu.py" 一次又一次地执行(它进行得太快了,看起来程序还没有结束)。不幸的是,我真的不明白为什么会这样。
到目前为止,我的解决方案是在程序的最后(while 循环之后)使用 "keyboard.send('ctrl+c')"。这可以防止终端再次重新执行命令 "python menu.py"。
一周前刚开始使用 python。目前我正在尝试编写一个小程序 class,它在终端中创建一个菜单。这个想法是使用向上/向下键浏览菜单。您可以通过按 enter select 菜单项。我使用模块 "keyboard".
控制按下的键为了使用我的 class,必须创建一个对象并通过方法 "add_menu" 添加菜单项。后面提到的方法有两个参数,第一个用于菜单项的名称,第二个用于传递一个函数,该函数将在按下回车时调用。
为了检查是否按下了某个键,我使用了模块键盘中的方法keyboard.on_press。如果按下某个键,方法 keyboard.on_press 将执行菜单对象的方法 handle_menu。 handle_menu 方法使用名为 "controller" 的列表来组织菜单项的 selection。基本上,它只是一个像 [0,0,1,0] 这样的列表。元素为 1 表示当前 selected 菜单项。
现在解决我的问题:我的菜单有一个菜单项 "Exit"。如果这是 selected 并按下回车键,我希望整个程序停止。因此,如果按下退出,属性 exit 将从 0 更改为 1。在我程序的 while 循环中,我总是检查 object.exit 是否为 != 1,否则程序应该结束。不知何故,这并不总是有效。如果我从一开始就立即向下滚动,而不在其他菜单项上按回车键,它就可以工作。但是,如果我在其他菜单项上多次按回车然后转到退出菜单项,程序不会再结束(或者只有当我按回车 10-20 次时)。感觉keyboard.on_press方法和while循环有时在后台解耦,运行异步?我不太明白这是怎么回事...
import keyboard #Using module keyboard
import os
class bcolors:
HEADER = '3[95m'
OKBLUE = '3[94m'
OKGREEN = '3[92m'
WARNING = '3[93m'
FAIL = '3[91m'
ENDC = '3[0m'
BOLD = '3[1m'
UNDERLINE = '3[4m'
def start_function():
print('Start works')
def save_function():
print('Save works')
def option_function():
print('Option works')
class c_menu:
def __init__ (self):
self.exit = 0
self.menu = []
self.functions = []
self.controller = []
def add_menu(self, menu, function):
self.menu.append(menu)
self.functions.append(function)
if len(self.controller) == 0:
self.controller.append(1)
else:
self.controller.append(0)
def start_menu(self):
os.system('cls' if os.name == 'nt' else 'clear')
for menu_item in range(len(self.menu)):
if self.controller[menu_item] == 1:
print(bcolors.WARNING + self.menu[menu_item])
else:
print(bcolors.OKBLUE + self.menu[menu_item])
def handle_menu(self, event):
os.system('cls' if os.name == 'nt' else 'clear')
if event.name == 'down':
if self.controller.index(1) != (len(self.controller) - 1):
self.controller.insert(0,0)
self.controller.pop()
elif event.name == 'up':
if self.controller.index(1) != 0:
self.controller.append(0)
self.controller.pop(0)
for menu_item in range(len(self.menu)): #printing all menu items with the right color
if self.controller[menu_item] == 1:
print(bcolors.WARNING + self.menu[menu_item])
else:
print(bcolors.OKBLUE + self.menu[menu_item])
if event.name == 'enter':
if self.functions[self.controller.index(1)] == 'exit':
self.exit = 1
return
self.functions[self.controller.index(1)]()
main_menu = c_menu()
main_menu.add_menu('Start', start_function)
main_menu.add_menu('Save', save_function)
main_menu.add_menu('Option', option_function)
main_menu.add_menu('Exit', 'exit')
main_menu.start_menu()
keyboard.on_press(main_menu.handle_menu)
while main_menu.exit != 1:
pass
我想我理解了这个问题。该程序实际上已正确结束,但是,最后按下的 "enter" 仍在某种缓冲区(或类似的东西)中,并且在程序结束后,终端命令 "python menu.py" 一次又一次地执行(它进行得太快了,看起来程序还没有结束)。不幸的是,我真的不明白为什么会这样。
到目前为止,我的解决方案是在程序的最后(while 循环之后)使用 "keyboard.send('ctrl+c')"。这可以防止终端再次重新执行命令 "python menu.py"。