我目前正在使用python / curses编写应用程序用户界面,我想知道是否可以要求用户在用户界面不断更新时按下键(cbreak模式)以隐藏或显示某些面板或窗口。
我阅读了有关curses的官方python文档并进行了一些尝试,但是即使使用cbreak模式和非阻塞输入模式(nodelay)已激活,我也无法使其正常工作(我成功获取了用户输入,但是在阻止UI的代价不是我想要的)。
所以我的问题很简单,可能吗?如果是的话,怎么办?
我可能误读了文档,但没有找到任何替代文档或示例。
我曾考虑过使应用程序具有多线程功能,但在这种情况下,我没有看到这对我有什么帮助。
感谢您的帮助,建议或指向详细文档的指针。
编辑:
最后,我得到了以下多线程代码,但并不令人满意。UI已按原样提供,但刷新后显示异常。
我还不明白为什么在隐藏考虑的面板的情况下curses.panel.hidden()返回False。似乎刷新与面板关联的窗口会取消隐藏面板或类似的东西。我真的迷路了!
import threading import curses, curses.panel import random import time gui = None class ui: def __init__(self): self.feeder = feeder(self) self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.curs_set(0) self.stdscr.keypad(1) self.win1 = curses.newwin(10, 50, 0, 0) self.win1.border(0) self.pan1 = curses.panel.new_panel(self.win1) self.win2 = curses.newwin(10, 50, 0, 0) self.win2.border(0) self.pan2 = curses.panel.new_panel(self.win2) self.win3 = curses.newwin(10, 50, 12, 0) self.win3.border(0) self.pan3 = curses.panel.new_panel(self.win3) self.win1.addstr(1, 1, "Window 1") self.win2.addstr(1, 1, "Window 2") self.win3.addstr(1, 1, "Press 's' to switch windows or 'q' to quit.") self.pan1.hide() self.win1.refresh() curses.panel.update_panels() self.win2.refresh() self.feeder.start() def ask(self): while True: self.win3.addstr(5,1, "Hidden = win1: "+str(self.pan1.hidden())+\ "win2:"+str(self.pan2.hidden()), 0) self.win3.refresh() k = self.win3.getkey() if k == 's': if self.pan1.hidden(): self.pan2.hide() self.pan1.show() self.win1.refresh() self.win3.addstr(2, 1, "Pan1 restored") else: self.pan1.hide() self.pan2.show() self.win2.refresh() self.win3.addstr(2, 1, "Pan2 restored") self.win3.addstr(5,1, "Hidden = win1: "+\ str(self.pan1.hidden())+\ " win2:"+str(self.pan2.hidden()), 0) elif k == 'q': break self.quit_ui() def quit_ui(self): self.feeder.stop() curses.nocbreak() self.stdscr.keypad(0) curses.curs_set(1) curses.echo() curses.endwin() exit(0) def display_data(self, window, data): window.addstr(3, 1, data, 0) class feeder(threading.Thread): # Fake U.I feeder def __init__(self, ui): super(feeder, self).__init__() self.running = False self.ui = ui self.count = 0 def stop(self): self.running = False def run(self): self.running = True self.feed() def feed(self): while self.running: self.ui.win1.addstr(3, 1, str(self.count)+\ ": "+str(int(round(random.random()*9999)))) self.ui.win1.addstr(4, 1, str(self.running)) self.ui.win2.addstr(3, 1, str(self.count)+\ ": "+str(int(round(random.random()*9999)))) self.ui.win2.addstr(4, 1, str(self.running)) time.sleep(0.5) self.count += 1 if __name__ == "__main__": gui = ui() gui.ask()
我终于成功地通过在double while循环中从sys.stdin中读取一个字节,然后避免使用另一个线程来使其工作。以下代码可能无法在MS Windows上运行,并且由于我不是专业开发人员,因此它可能未经过优化或引发未捕获的错误,但这只是为了使我了解事情的工作原理而准备的草稿(尽管欢迎发表评论) )。特别感谢Paul Griffiths指导我使用sys.stdin。
#!/usr/bin/python # -*- coding: iso-8859-1 -*- import curses, curses.panel import random import time import sys import select gui = None class ui: def __init__(self): self.stdscr = curses.initscr() curses.noecho() curses.cbreak() curses.curs_set(0) self.stdscr.keypad(1) self.win1 = curses.newwin(10, 50, 0, 0) self.win1.border(0) self.pan1 = curses.panel.new_panel(self.win1) self.win2 = curses.newwin(10, 50, 0, 0) self.win2.border(0) self.pan2 = curses.panel.new_panel(self.win2) self.win3 = curses.newwin(10, 50, 12, 0) self.win3.border(0) self.pan3 = curses.panel.new_panel(self.win3) self.win1.addstr(1, 1, "Window 1") self.win2.addstr(1, 1, "Window 2") self.win3.addstr(1, 1, "Press 's' to switch windows or 'q' to quit.") self.pan1.hide() def refresh(self): curses.panel.update_panels() self.win2.refresh() self.win1.refresh() def switch_pan(self): if self.pan1.hidden(): self.pan2.bottom() self.pan2.hide() self.pan1.top() self.pan1.show() else: self.pan1.bottom() self.pan1.hide() self.pan2.top() self.pan2.show() self.refresh() def quit_ui(self): curses.nocbreak() self.stdscr.keypad(0) curses.curs_set(1) curses.echo() curses.endwin() print "UI quitted" exit(0) class feeder: # Fake U.I feeder def __init__(self): self.running = False self.ui = ui() self.count = 0 def stop(self): self.running = False def run(self): self.running = True self.feed() def feed(self): while self.running : while sys.stdin in select.select([sys.stdin], [], [], 0)[0]: line = sys.stdin.read(1) if line.strip() == "q": self.stop() self.ui.quit_ui() break elif line.strip() == "s": self.ui.switch_pan() self.ui.win1.addstr(3, 1, str(self.count)+\ ": "+str(int(round(random.random()*999)))) self.ui.win1.addstr(4, 1, str(self.running)) self.ui.win2.addstr(3, 1, str(self.count)+\ ": "+str(int(round(random.random()*999)))) self.ui.win2.addstr(4, 1, str(self.running)) self.ui.refresh() time.sleep(0.1) self.count += 1 if __name__ == "__main__": f = feeder() f.run()