简体   繁体   中英

Print a threading function in curses, Python

In my project I have to print some data stored in a database on the console. I have two functions that return string. I should print those data in two columns. I thought of using the module curses in python to create those two columns. So far all is good. Another thing, is that my two function use the threading.Timer. So the string generated changes every 10 seconds for example if I set my Timer on 10. So when I put the result of my function on the addstr() of a column, it prints the first String correctly, but nothing changes even if my string change. Otherwise when I resize for example the console, I notice that the string changes. Here is my code :

import sys,os
import curses , curses.panel 
import datetime
import time
import threading



def time_func():
    printStr = threading.Timer(10,time_func)
    printStr.start()
    s = "Simple example that display datetime \n" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") 
    return s 

def draw_menu():


    k = 0
    cursor_x = 0
    cursor_y = 0


    # Clear and refresh the screen
    stdscr = curses.initscr()
    stdscr.clear()
    stdscr.refresh()

    # Initialize colors in curses
    curses.start_color()
    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
    curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_WHITE)
    curses.curs_set(0)
    # Loop where k is the last character pressed
    while (k != ord('q')):

        # Declaration of strings
        statusbarstr = "Press 'q' to exit | STATUS BAR "

        '''Draw borders of the different columns'''
        height, width = stdscr.getmaxyx()
        stdscr.border()
        stdscr.vline(1, 3 * height // 4, '|', width - 2)
        stdscr.vline(1, height // 4, '|', width - 2)
        stdscr.refresh()

        '''Initialize the Statistics column'''
        column_one = curses.newwin(height - 2, 3 * width // 4, 1,
                                           1)
        _, a_x = column_one.getmaxyx()
        column_one.attron(curses.color_pair(1))
        column_one.attron(curses.A_BOLD)
        column_one.addstr(0, a_x // 2 - 2, "column one")
        column_one.hline(1, 0, '-', a_x)
        column_one.attroff(curses.color_pair(1))
        column_one.attroff(curses.A_BOLD)

        # I want to add my string here for example : 
        line = time_func()
        column_one.addstr(3,1, line)


        column_one.noutrefresh()

        '''Initialize the Alerts column'''
        column_two = curses.newwin(height - 2, width // 4, 1,
                                       3 * width // 4 )
        _, s_x = column_two.getmaxyx()
        column_two.attron(curses.color_pair(1))
        column_two.attron(curses.A_BOLD)
        column_two.addstr(0, s_x // 2 - 5, "column two")
        column_two.hline(1, 0, '-', s_x)
        column_two.attroff(curses.color_pair(1))
        column_two.attroff(curses.A_BOLD)

        column_two.addstr(3, s_x // 2 - 5,"test")

        column_two.noutrefresh()



        # Render status bar
        stdscr.attron(curses.color_pair(3))
        stdscr.addstr(height-1, 0, statusbarstr)
        stdscr.addstr(height-1, len(statusbarstr), " " * (width - len(statusbarstr) - 1))
        stdscr.attroff(curses.color_pair(3))

        # Turning on attributes for title
        stdscr.attron(curses.color_pair(2))
        stdscr.attron(curses.A_BOLD)

        # Rendering title


        # Turning off attributes for title
        stdscr.attroff(curses.color_pair(2))
        stdscr.attroff(curses.A_BOLD)

        # Print rest of text

        stdscr.move(height - 2, width - 2)

        # Refresh the screen
        stdscr.refresh()
        # Wait for next input
        k = stdscr.getch()

def main():
    curses.wrapper(draw_menu())

if __name__ == "__main__":
    main()

The curses function draw_menu is waiting for input at the end of the loop. If you resize the terminal, that

k = stdscr.getch()

returns a KEY_RESIZE , and runs through the loop again.

You could change that to wait a short time before giving up on the getch . That would return a -1 .

Usually that's done using timeout (in curses), eg, 50 milliseconds. There's a wrapper for that in Python (and by the way its description is incorrect). You should read the ncurses manual page for timeout .

Sometimes people say to use nodelay , which is usually poor advice since it would make the draw_menu thread use most of the CPU time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM