如何在 curses 的文本框中添加滚动?
How to add scrolling in a textbox in curses?
目前,当我们到达文本框区域的末尾时,我们只是移动到框外的下一行。我如何实现滚动,以便当我们到达末尾并尝试移动到下一行时,顶行消失并且整个文本正文向上移动?
例如:
+-------+
|hello1 |
|hello2 |
|hello3 |
|hello4 |
|hello5 |
+-------+
按回车后:-
+-------+
|hello2 |
|hello3 |
|hello4 |
|hello5 |
| |
+-------+
这是代码,我知道 curses 的文本板,但它不是我需要的。
import curses
from curses import textpad
import time
class notepad:
def __init__(self, stdscr, topleft, bottomright, starttext = ""):
self.topleft = topleft
self.bottomright = bottomright
self.stdscr = stdscr
self.text = starttext
self.curspos = 0
def box(self):
curses.textpad.rectangle(self.stdscr, self.topleft[0], self.topleft[1], self.bottomright[0], self.bottomright[1])
def get_input(self, key):
if not key == -1:
if key == curses.KEY_LEFT:
self.curspos -= 1
elif key == curses.KEY_RIGHT:
if self.curspos < len(self.text):
self.curspos += 1
elif key == curses.KEY_UP:
self.curspos -= self.width
elif key == curses.KEY_DOWN:
if self.curspos//self.width < len(self.text)//self.width:
self.curspos += self.width - (self.curspos%self.width - len(self.text)%self.width)
elif key == curses.KEY_BACKSPACE:
self.text = self.text[:self.curspos][:-1] + self.text[self.curspos:]
self.curspos -= 1
elif key == curses.KEY_ENTER or key == 10 or key == 13:
self.text = self.text[:self.curspos] + " "*(self.width - (len(self.text[:self.curspos])%self.width)) + self.text[self.curspos:]
self.curspos += 1
self.curspos += self.width - (self.curspos%self.width - len(self.text)%self.width)
else:
self.text = self.text[:self.curspos] + chr(key) + self.text[self.curspos:]
self.curspos += 1
def display(self):
self.width = (self.bottomright[1]-1) - (self.topleft[1]+1)
if self.curspos < 0:
self.curspos = 0
#disply text
for i in range(len(self.text)):
self.stdscr.addstr( self.topleft[0]+1 + (i//self.width) ,
self.topleft[1]+1 +i%self.width ,
self.text[i]
)
#display fake cursor
if self.curspos < len(self.text):
self.stdscr.addstr(self.topleft[0]+1 + (self.curspos//self.width) , self.topleft[1]+1 + self.curspos%self.width, self.text[self.curspos], curses.A_REVERSE)
else:
self.stdscr.addstr(self.topleft[0]+1 + (self.curspos//self.width) , self.topleft[1]+1 + self.curspos%self.width, " ", curses.A_REVERSE)
def main():
run = True
stdscr = curses.initscr()
stdscr.nodelay(True)
stdscr.keypad(True)
curses.curs_set(False)
curses.start_color()
curses.noecho()
curses.cbreak()
notepad1 = notepad(stdscr, [0,0], [20, 30])
try:
while run:
start = time.time()
stdscr.erase()
key = stdscr.getch()
notepad1.box()
notepad1.get_input(key)
notepad1.display()
stdscr.refresh()
time.sleep(max(0.05 - (time.time() - start), 0))
finally:
curses.echo()
curses.nocbreak()
curses.curs_set(True)
stdscr.keypad(False)
stdscr.nodelay(False)
curses.endwin()
main()
既然你评论说你想保留文本但将其滚动到屏幕之外,你需要在你的初始化中这样的东西:
self.scroll_lines = 0
然后当你想向下滚动一行时,只需使用:
self.scroll_lines += 1
你的显示函数看起来像这样:
#disply text
text_offset = self.scroll_lines*self.width
for i in range(text_offset, len(self.text)):
self.stdscr.addstr( self.topleft[0]+1 + (i//self.width-self.scroll_lines) ,
self.topleft[1]+1 +i%self.width ,
self.text[i]
)
我将把它留作练习,供您正确放置光标。
目前,当我们到达文本框区域的末尾时,我们只是移动到框外的下一行。我如何实现滚动,以便当我们到达末尾并尝试移动到下一行时,顶行消失并且整个文本正文向上移动?
例如:
+-------+
|hello1 |
|hello2 |
|hello3 |
|hello4 |
|hello5 |
+-------+
按回车后:-
+-------+
|hello2 |
|hello3 |
|hello4 |
|hello5 |
| |
+-------+
这是代码,我知道 curses 的文本板,但它不是我需要的。
import curses
from curses import textpad
import time
class notepad:
def __init__(self, stdscr, topleft, bottomright, starttext = ""):
self.topleft = topleft
self.bottomright = bottomright
self.stdscr = stdscr
self.text = starttext
self.curspos = 0
def box(self):
curses.textpad.rectangle(self.stdscr, self.topleft[0], self.topleft[1], self.bottomright[0], self.bottomright[1])
def get_input(self, key):
if not key == -1:
if key == curses.KEY_LEFT:
self.curspos -= 1
elif key == curses.KEY_RIGHT:
if self.curspos < len(self.text):
self.curspos += 1
elif key == curses.KEY_UP:
self.curspos -= self.width
elif key == curses.KEY_DOWN:
if self.curspos//self.width < len(self.text)//self.width:
self.curspos += self.width - (self.curspos%self.width - len(self.text)%self.width)
elif key == curses.KEY_BACKSPACE:
self.text = self.text[:self.curspos][:-1] + self.text[self.curspos:]
self.curspos -= 1
elif key == curses.KEY_ENTER or key == 10 or key == 13:
self.text = self.text[:self.curspos] + " "*(self.width - (len(self.text[:self.curspos])%self.width)) + self.text[self.curspos:]
self.curspos += 1
self.curspos += self.width - (self.curspos%self.width - len(self.text)%self.width)
else:
self.text = self.text[:self.curspos] + chr(key) + self.text[self.curspos:]
self.curspos += 1
def display(self):
self.width = (self.bottomright[1]-1) - (self.topleft[1]+1)
if self.curspos < 0:
self.curspos = 0
#disply text
for i in range(len(self.text)):
self.stdscr.addstr( self.topleft[0]+1 + (i//self.width) ,
self.topleft[1]+1 +i%self.width ,
self.text[i]
)
#display fake cursor
if self.curspos < len(self.text):
self.stdscr.addstr(self.topleft[0]+1 + (self.curspos//self.width) , self.topleft[1]+1 + self.curspos%self.width, self.text[self.curspos], curses.A_REVERSE)
else:
self.stdscr.addstr(self.topleft[0]+1 + (self.curspos//self.width) , self.topleft[1]+1 + self.curspos%self.width, " ", curses.A_REVERSE)
def main():
run = True
stdscr = curses.initscr()
stdscr.nodelay(True)
stdscr.keypad(True)
curses.curs_set(False)
curses.start_color()
curses.noecho()
curses.cbreak()
notepad1 = notepad(stdscr, [0,0], [20, 30])
try:
while run:
start = time.time()
stdscr.erase()
key = stdscr.getch()
notepad1.box()
notepad1.get_input(key)
notepad1.display()
stdscr.refresh()
time.sleep(max(0.05 - (time.time() - start), 0))
finally:
curses.echo()
curses.nocbreak()
curses.curs_set(True)
stdscr.keypad(False)
stdscr.nodelay(False)
curses.endwin()
main()
既然你评论说你想保留文本但将其滚动到屏幕之外,你需要在你的初始化中这样的东西:
self.scroll_lines = 0
然后当你想向下滚动一行时,只需使用:
self.scroll_lines += 1
你的显示函数看起来像这样:
#disply text
text_offset = self.scroll_lines*self.width
for i in range(text_offset, len(self.text)):
self.stdscr.addstr( self.topleft[0]+1 + (i//self.width-self.scroll_lines) ,
self.topleft[1]+1 +i%self.width ,
self.text[i]
)
我将把它留作练习,供您正确放置光标。