Search code examples
pythoncurses

Wait for input for 1 second in python


I'm trying to make a note application in Python using curses. To the bottom left, should be a clock that updates every second.

The issue I now have is that it either has to sleep 1 second, or wait for input.

Is it possible to wait for input for 1 second and continue if no input it registered?

The reason I want to do this, is to prevent delay when moving around in the application.

I was thinking something like multi-threading would do the job, but got some issues there too.

This is the code I have so far:

#!/usr/bin/env python3
import curses
import os
import time
import datetime
import threading


def updateclock(stdscr):
    while True:
        height, width = stdscr.getmaxyx()
        statusbarstr = datetime.datetime.now().strftime(' %A')[:4] + datetime.datetime.now().strftime(' %Y-%m-%d | %H:%M:%S')
        stdscr.addstr(height-1, 0, statusbarstr)

        time.sleep(1)

def draw_menu(stdscr):
    k = 0

    stdscr.clear()
    stdscr.refresh()

    threading.Thread(target=updateclock, args=stdscr).start()

    cursor_y = 0
    cursor_x = 0

    while (k != ord('q')):
    #while True:

        stdscr.clear()
        height, width = stdscr.getmaxyx()

        stdscr.addstr(height//2, width//2, "Some text in the middle")

        if k == curses.KEY_DOWN:
            cursor_y = cursor_y + 1
        elif k == curses.KEY_UP:
            cursor_y = cursor_y - 1
        elif k == curses.KEY_RIGHT:
            cursor_x = cursor_x + 1
        elif k == curses.KEY_LEFT:
            cursor_x = cursor_x - 1

        stdscr.refresh()
        #time.sleep(1)

        # Wait for next input
        k = stdscr.getch()


curses.wrapper(draw_menu)

The code looks pretty messy, and it's the first time I've mainly focused on the curses function.

Is it possible to only wait for input k = stdscr.getch() for 1 second?


Solution

  • By default getch will block until you have a character input ready. If nodelay mode is True, then you will either get the character value (0-255) of the character that is ready, or you will get a -1 indicating that no character value is ready.

    stdscr.nodelay(True) #Set nodelay to be True, it won't block anymore
    k = stdscr.getch() #Either the next character of input, or -1