Python curses:让回车键终止文本框?
Python curses: Make enter key terminate Textbox?
我有一个应用程序,要求人们输入他们的用户名和密码。我希望他们只需按回车键即可发送名称和密码。为此,我做了这个:
import curses, curses.textpad
def setup_input():
inp = curses.newwin(8,55, 0,0)
inp.addstr(1,1, "Please enter your username:")
sub = inp.subwin(2,1)
sub.border()
sub2 = sub.subwin(3,2)
global tb
tb = curses.textpad.Textbox(sub2)
inp.refresh()
tb.edit(enter_is_terminate)
def enter_is_terminate(x):
if x == 10:
tb.do_command(7)
tb.do_command(x)
setup_input()
不幸的是,这没有按预期工作。终止的标准字符(由 CTRL+G 触发)是 7,输入字符是 10,但是使用上面的代码,所有其他键仍然可以正确处理,但是当我按回车键时,它只是给我一个换行符,而不是终止文本框的编辑模式。我做错了什么?
Found this on the documentation:
If validator is supplied, it must be a function. It will be called for each keystroke entered with the keystroke as a parameter; command dispatch is done on the result.
所以不用 运行 tb.do_command
你自己,只需 return 你想要 'input'.
的密钥
def enter_is_terminate(x):
if x == 10:
return 7
此外,现在您不需要将 tb
定义为全局变量,这通常是一件好事。 :)
如果您对一行输入感到满意,您就不必自己处理回车键。
在 documentation 上是这样说的:
Control-J -- Terminate if the window is 1 line, otherwise insert newline.
因此,如果您 define the textbox's sub window with line count of 1 您不需要自己处理回车键。
def setup_input():
inp = curses.newwin(8,55, 0,0)
inp.addstr(1,1, "Please enter your username:")
sub = inp.subwin(3, 41, 2, 1)
sub.border()
sub2 = sub.subwin(1, 40, 3, 2)
tb = curses.textpad.Textbox(sub2)
inp.refresh()
tb.edit()
我还给了 sub
一个特定的行和列数,因此边框很好地围绕着文本框。
阅读源代码有帮助。这是一个有效的验证器:
def enter_is_terminate(x):
if x == 10:
x = 7
return x
验证器必须 return 一个字符,edit
函数使用 do_command
:
检查该字符
def edit(self, validate=None):
"Edit in the widget window and collect the results."
while 1:
ch = self.win.getch()
if validate:
ch = validate(ch)
if not ch:
continue
if not self.do_command(ch):
break
self.win.refresh()
return self.gather()
和 do_command
只有 returns 0 对于两种情况 (a) ASCII BEL 和 (b) 单行换行符 window:
elif ch == curses.ascii.BEL: # ^g
return 0
elif ch == curses.ascii.NL: # ^j
if self.maxy == 0:
return 0
elif y < self.maxy:
self.win.move(y+1, 0)
也许我的解决方案会有所帮助,我制作了一个文本框,它通过按回车键终止,所以你可以用它做任何你想做的事 n hv fun:-
def txtpnl(stdscr, y=10, xl=10, wl=20, HIDE_WORDS = False):
wl += xl + 2
s = ''
textpad.rectangle(stdscr, y, xl, y + 2, wl)
stdscr.addstr(y + 1, xl + 1, '')
cp = 0
while True:
textpad.rectangle(stdscr, y, xl, y + 2, wl)
stdscr.addstr(y + 1, xl + 1 + cp, '')
k = stdscr.getch()
if k == KEY_ENTER or k in [10, 13]:
break
elif k == KEY_UP or k == KEY_DOWN:
pass
elif k == KEY_BACKSPACE or k == 8:
if cp > 0: cp -= 1
stdscr.addstr(y + 1, xl + 1, " " * len(s))
s = s[:cp]+s[cp+1:]
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k == KEY_LEFT or k == 27:
if not cp:
pass
else:
cp -= 1
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k == KEY_RIGHT or k == 26:
if cp == len(s):
pass
else:
cp += 1
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k in [KEY_DC, 127]:
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp + 1:] + " "))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp + 1:] + " ")
stdscr.addstr(y + 1, xl + 1, s[:cp])
s = s[:cp] + s[cp + 1:]
else:
if len(s) < wl - xl - 2:
if cp == len(s):
s += str(chr(k))
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1, "*"*len(s))
else:
stdscr.addstr(y + 1, xl + 1, s)
else:
s = s[:cp] + str(chr(k)) + s[cp:]
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + len(s[:cp + 1]), "*"*len(s[cp + 1:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp + 1]))
else:
stdscr.addstr(y + 1, xl + 1 + len(s[:cp + 1]), s[cp + 1:])
stdscr.addstr(y + 1, xl + 1, s[:cp + 1])
cp += 1
return s
我有一个应用程序,要求人们输入他们的用户名和密码。我希望他们只需按回车键即可发送名称和密码。为此,我做了这个:
import curses, curses.textpad
def setup_input():
inp = curses.newwin(8,55, 0,0)
inp.addstr(1,1, "Please enter your username:")
sub = inp.subwin(2,1)
sub.border()
sub2 = sub.subwin(3,2)
global tb
tb = curses.textpad.Textbox(sub2)
inp.refresh()
tb.edit(enter_is_terminate)
def enter_is_terminate(x):
if x == 10:
tb.do_command(7)
tb.do_command(x)
setup_input()
不幸的是,这没有按预期工作。终止的标准字符(由 CTRL+G 触发)是 7,输入字符是 10,但是使用上面的代码,所有其他键仍然可以正确处理,但是当我按回车键时,它只是给我一个换行符,而不是终止文本框的编辑模式。我做错了什么?
Found this on the documentation:
If validator is supplied, it must be a function. It will be called for each keystroke entered with the keystroke as a parameter; command dispatch is done on the result.
所以不用 运行 tb.do_command
你自己,只需 return 你想要 'input'.
def enter_is_terminate(x):
if x == 10:
return 7
此外,现在您不需要将 tb
定义为全局变量,这通常是一件好事。 :)
如果您对一行输入感到满意,您就不必自己处理回车键。
在 documentation 上是这样说的:
Control-J -- Terminate if the window is 1 line, otherwise insert newline.
因此,如果您 define the textbox's sub window with line count of 1 您不需要自己处理回车键。
def setup_input():
inp = curses.newwin(8,55, 0,0)
inp.addstr(1,1, "Please enter your username:")
sub = inp.subwin(3, 41, 2, 1)
sub.border()
sub2 = sub.subwin(1, 40, 3, 2)
tb = curses.textpad.Textbox(sub2)
inp.refresh()
tb.edit()
我还给了 sub
一个特定的行和列数,因此边框很好地围绕着文本框。
阅读源代码有帮助。这是一个有效的验证器:
def enter_is_terminate(x):
if x == 10:
x = 7
return x
验证器必须 return 一个字符,edit
函数使用 do_command
:
def edit(self, validate=None):
"Edit in the widget window and collect the results."
while 1:
ch = self.win.getch()
if validate:
ch = validate(ch)
if not ch:
continue
if not self.do_command(ch):
break
self.win.refresh()
return self.gather()
和 do_command
只有 returns 0 对于两种情况 (a) ASCII BEL 和 (b) 单行换行符 window:
elif ch == curses.ascii.BEL: # ^g
return 0
elif ch == curses.ascii.NL: # ^j
if self.maxy == 0:
return 0
elif y < self.maxy:
self.win.move(y+1, 0)
也许我的解决方案会有所帮助,我制作了一个文本框,它通过按回车键终止,所以你可以用它做任何你想做的事 n hv fun:-
def txtpnl(stdscr, y=10, xl=10, wl=20, HIDE_WORDS = False):
wl += xl + 2
s = ''
textpad.rectangle(stdscr, y, xl, y + 2, wl)
stdscr.addstr(y + 1, xl + 1, '')
cp = 0
while True:
textpad.rectangle(stdscr, y, xl, y + 2, wl)
stdscr.addstr(y + 1, xl + 1 + cp, '')
k = stdscr.getch()
if k == KEY_ENTER or k in [10, 13]:
break
elif k == KEY_UP or k == KEY_DOWN:
pass
elif k == KEY_BACKSPACE or k == 8:
if cp > 0: cp -= 1
stdscr.addstr(y + 1, xl + 1, " " * len(s))
s = s[:cp]+s[cp+1:]
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k == KEY_LEFT or k == 27:
if not cp:
pass
else:
cp -= 1
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k == KEY_RIGHT or k == 26:
if cp == len(s):
pass
else:
cp += 1
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp:])
stdscr.addstr(y + 1, xl + 1, s[:cp])
elif k in [KEY_DC, 127]:
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + cp, "*"*len(s[cp + 1:] + " "))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp]))
else:
stdscr.addstr(y + 1, xl + 1 + cp, s[cp + 1:] + " ")
stdscr.addstr(y + 1, xl + 1, s[:cp])
s = s[:cp] + s[cp + 1:]
else:
if len(s) < wl - xl - 2:
if cp == len(s):
s += str(chr(k))
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1, "*"*len(s))
else:
stdscr.addstr(y + 1, xl + 1, s)
else:
s = s[:cp] + str(chr(k)) + s[cp:]
if HIDE_WORDS:
stdscr.addstr(y + 1, xl + 1 + len(s[:cp + 1]), "*"*len(s[cp + 1:]))
stdscr.addstr(y + 1, xl + 1, "*"*len(s[:cp + 1]))
else:
stdscr.addstr(y + 1, xl + 1 + len(s[:cp + 1]), s[cp + 1:])
stdscr.addstr(y + 1, xl + 1, s[:cp + 1])
cp += 1
return s