curses를 사용하여 간단한 GUI를 작성하려고하지만 크기 조정 및 화면 다시 그릴 때 약간의 문제가 있습니다. 다음은 내 코드입니다 :Python curses - 텍스트 입력 중에 터미널 크기 조정
import curses
import curses.textpad as textpad
class editor (object):
def __init__(self, stdscreen):
self.screen = stdscreen
self.height,self.width = self.screen.getmaxyx()
self.draw_screen()
while True:
# Check if the screen has been resized
resize = curses.is_term_resized(self.height, self.width)
if resize:
self.height,self.width = self.screen.getmaxyx()
self.draw_screen()
curses.noecho()
text = textpad.Textbox(self.text).edit(validate=self.validate)
self.body.addstr(0,0, str(text), curses.A_NORMAL)
self.body.refresh()
self.text.erase()
def draw_screen (self):
self.screen.clear()
self.header=self.screen.subwin(1,self.width,0,0)
self.body=self.screen.subwin(self.height-3,self.width,1,0)
self.text=self.screen.subwin(1,self.width,self.height-2,0)
self.footer=self.screen.subwin(self.height-1,0)
header_text = "{0:<{n}}".format("Header", n=self.width-1)
self.header.addstr(0,0, header_text, curses.A_REVERSE)
self.footer.addstr(0,0, "^W", curses.A_REVERSE)
self.footer.addstr(0,2, " Quit", curses.A_NORMAL)
self.header.noutrefresh()
self.body.noutrefresh()
self.footer.noutrefresh()
self.text.noutrefresh()
curses.doupdate()
def validate (self, ch):
# If resize event redraw screen
if ch==curses.KEY_RESIZE:
self.height,self.width = self.screen.getmaxyx()
self.draw_screen()
if ch==23: # ^w quit
exit()
else:
return ch
if __name__=="__main__":
curses.wrapper(editor)
터미널이이 같은 예상 작품 크기가 조정되지되어
,하지만, 터미널 창을 확대 할 때 각각 상단과 하단 행 머리글과 바닥 글 이동, 커서 남아있는 동안 Enter 키를 눌러 문자열을 받아 들일 때까지 이전 위치에 놓습니다. 축소 할 때와 동일합니다. 단,이 경우 커서가 바닥 글에 들어가고 바닥 글의 내용이 반환됩니다. 문제를 디버깅하려고했는데 하위 창이 제대로 움직이는 것처럼 보였지만 커서가 움직이지 않는 것으로 나타났습니다. 나도 시도했다
self.text.move(0,0)
커서를 오른쪽 위치로 다시 이동했지만 작동하지 않았다.
보너스 : 크기 조정 작업 전에 삽입 한 텍스트를 보존하고 크기가 조정 된 표시된 화면에 추가하려면 어떻게합니까?
편집 : 더 많은 디버깅을 한 후에 나는 "종류"의 작동 (그러나 추악하고 해킹) 인 의사 솔루션을 생각해 냈습니다. 내가를 무슨 짓을했는지
import curses
import curses.textpad as textpad
class my_textbox(textpad.Textbox):
def edit(self, validate=None):
while 1:
ch = self.win.getch()
# Return a list instead of a string if the last key was a resize
if ch==curses.KEY_RESIZE:
return[self.gather(),True]
if validate:
ch = validate(ch)
if not ch:
continue
if not self.do_command(ch):
break
self.win.refresh()
return self.gather()
class editor (object):
def __init__(self, stdscreen):
self.screen = stdscreen
self.height,self.width = self.screen.getmaxyx()
# Initialize a variable to store the previous text
self.ptext=None
curses.noecho()
self.draw_screen()
while True:
# Check if the screen has been resized
resize = curses.is_term_resized(self.height, self.width)
if resize:
self.height,self.width = self.screen.getmaxyx()
self.draw_screen()
text = my_textbox(self.text).edit(validate=self.validate)
# If the window has been resized (aka textbox returned a list)
if isinstance (text, list):
text=text[0]
# Store the previous text
self.ptext=text.strip()
continue
self.body.addstr(0,0, str(text), curses.A_NORMAL)
self.body.refresh()
self.text.erase()
def draw_screen (self):
self.screen.clear()
self.header=self.screen.subwin(1,self.width,0,0)
self.body=self.screen.subwin(self.height-3,self.width,1,0)
self.text=self.screen.subwin(1,self.width,self.height-2,0)
self.footer=self.screen.subwin(self.height-1,0)
header_text = "{0:<{n}}".format("Header", n=self.width-1)
self.header.addstr(0,0, header_text, curses.A_REVERSE)
# If there was text previous to resize
if self.ptext:
# To prevent _curses.error: addwstr() returned ERR
# when shrinking window cut out the last character
# (!) Raises ERR anyway when shrinking with double click from
# titlebar, also, when resizing is too fast, ptext become a series of ^?
if len(self.ptext)<self.width-1:
self.text.addstr(0,0,self.ptext.strip())
else:
self.ptext=self.ptext[:self.width-1]
self.text.addstr(0,0,self.ptext.strip())
self.footer.addstr(0,0, "^W", curses.A_REVERSE)
self.footer.addstr(0,2, " Quit", curses.A_NORMAL)
self.header.noutrefresh()
self.body.noutrefresh()
self.footer.noutrefresh()
self.text.noutrefresh()
curses.doupdate()
def validate (self, ch):
if ch==23: # ^w quit
exit()
else:
return ch
if __name__=="__main__":
curses.wrapper(editor)
는 : 창문의 크기를 조정할 때 문자열 대신 목록을 반환하도록
나는, 텍스트 상자 클래스의 편집 방법을 재정의.입력 루프에서 창의 크기가 조정되면 이전주기가 저장되고 새주기가 시작됩니다.
이전 텍스트가있는 경우 그리기 기능이이를 하위 창에 추가합니다.
노트 :
에 의해 크기 조정 제목 표시 줄을 두 번 클릭 던져에서 오류가 발생하고 크기 조정은 "너무 빨리"인 경우 문자열이 쓰레기로 대체한다 (실제로는 2^64 "? ^"이다 -1).
(n) curses의 기능 대부분이 크기 조정이 불가능한 터미널을 염두에두고 작성 되었기 때문에 구현은 이해가되지만 적어도 필자와 같은 비교적 새로운 Python에서는 직관적이지 않습니다. 모든.
의견을 보내 주셔서 감사합니다. 더 많은 실험을 수행했으며 문제가 잘린 창인지 확신 할 수 없습니다. 나는 내가 발견 한 것으로 질문을 업데이트했다. 나는 패드로 몇 가지 테스트를 할 수 있다고 생각하지만 실제로 많은 작업이있는 것으로 보인다. –