Can I show strings on ncurses screen without getch

2019-08-04 00:24发布

问题:

Currently, I know only one way to show strings using ncurses library, like as below:

import curses

stdscr = curses.initscr()
stdscr.addch(0,0,'x')
stdscr.getch()

But I've met a problem when I want to make a falling function of string.

import curses
import time

stdscr = curses.initscr()
y=1
def fall():
    global y
    stdscr.addstr(y,0,'x')
    stdscr.move(y-1,0)
    stdscr.clrtoeol()
    y += 1 
    stdscr.getch()

while True:
    time.sleep(0.2)
    fall()

If I remove this getch() function, I can't see the ncurses screen. But if I put it in. I have to touch some key on my keyboard then the string could fall.

Is there a way I can make the string automatically falling without hit keyboard or mouse?

回答1:

You have to explicitly update the screen, either by calling the refresh() method on the window (stdscr in your example) or by calling curses.doupdate().

This is due to the fact that curses was written years ago, when terminal where pretty slow and it was really important to make modifications efficiently. With an explicit update you can first change the screen how you want and then update it in a single operation, instead of doing an update for every single operation.



回答2:

Refresh at the point you wants to reflect changes on your screen. I am not rectifying but modifying my draw square code in previous answer, below my own code using curses library(added comments so that it can be helpful for someone new):

from curses import *
import random, time 
def main(stdscr):
  start_color() # call after initscr(), to use color, not needed with wrapper 
  stdscr.clear() # clear above line. 
  stdscr.addstr(1, 3, "Fig: RAINING", A_UNDERLINE|A_BOLD)
  # init some color pairs:    
  init_pair(10, COLOR_WHITE, COLOR_WHITE) # BG color
  init_pair(1, COLOR_RED, COLOR_WHITE)
  init_pair(2, COLOR_BLUE, COLOR_WHITE)
  init_pair(3, COLOR_YELLOW, COLOR_WHITE)
  init_pair(4, COLOR_MAGENTA, COLOR_WHITE)
  init_pair(5, COLOR_CYAN, COLOR_WHITE)
  # First draw a white square as 'background'
  bg  = ' '  # background is blank 
  for x in range(3, 3 + 75): # horizontal c: x-axis
    for y in range(4, 4 + 20): # vertical r: y-axis
      stdscr.addstr(y, x, bg, color_pair(10))
  stdscr.refresh()  # refresh screen to reflect 
  stdscr.addstr(28, 0, 'Press Key to exit: ')
  # Raining   
  drop = '#' # drop is # 
  while True: # runs infinitely 
    xl = random.sample(range(3, 3+75), 25) # generate 25 random x-positions
    for y in range(5, 4 + 20): # vertical 
      for x in xl:
        stdscr.addstr(y-1, x, bg, color_pair(10)) #clear drops @previous row
        stdscr.addstr(y, x, drop, color_pair(random.randint(1, 5)))
      stdscr.refresh() # refresh each time,  # ^^ add drops at next row
      time.sleep(0.5)  #sleep for moving.. 
    for x in xl: # clear last row, make blank  
      stdscr.addstr(23, x, ' ', color_pair(10))
  stdscr.getkey() # it doesn't work in this code
wrapper(main) #Initialize curses and call another callable object, func,

Snap-sort of one iteration:

two iterations: http://s1.postimg.org/ehnvucp1p/rain.gif