Search code examples
pythoncurses

Python/Curses: Nothing happens on first key press


The code:

from curses import curs_set, KEY_RESIZE, newwin, resize_term, wrapper
from curses.panel import *


VERSION = '0.0.0a'


class Editor:
    def __init__(self, stdscr):
        curs_set(0)
        self.screen = stdscr
        self.max_rows, self.max_cols = self.screen.getmaxyx()
        self.panel = {
            'titlebar': EditorPanel(1, self.max_cols, 0, 0),
            'menubar': EditorPanel(1, self.max_cols-1, 2, 1)
        }
        self.panel['titlebar'].addstr(0, 0, f'Yedit {VERSION}')
        self.panel['menubar'].addstr(0, 0, 'File | Edit | View | Help')
        self.update()

    def input_handler(self):
        ch = self.screen.getch()
        if ch == ord('q'):
            return False
        elif ch == KEY_RESIZE:
            resize_term(*self.screen.getmaxyx())
            self.update()
        elif ch == ord('m'):
            # print(ch)
            self.panel['menubar'].toggle_visibility()

        return True

    def update(self):
        for key in self.panel:
            for argv in self.panel[key].text:
                self.panel[key].window.addstr(*argv)
            self.panel[key].window.refresh()
        update_panels()


class EditorPanel:
    def __init__(self, rows, cols, y, x):
        self.window = newwin(rows, cols, y, x)
        self.panel = new_panel(self.window)
        self.text = []

    def addstr(self, y, x, text):
        self.text.append((y, x, text))

    def toggle_visibility(self):
        if self.panel.hidden():
            self.panel.show()
        else:
            self.panel.hide()
        self.window.refresh()
        update_panels()


def main(stdscr):
    yedit = Editor(stdscr)
    while yedit.input_handler():
        continue


wrapper(main)

The problem: When the 'm' key is pressed, it toggles the visibility of the panel, but absolutely nothing happens on the first press of 'm.' The print(ch) statement was included to test this. I've omitted a final else statement I used to verify that ch wasn't some unexpected value. In contrast, pressing 'q' exits the program as expected on the first key press.

What is going on?


Solution

  • You've got refreshes sprinkled all over the place in your code. I'm not sure exactly why the first key press isn't working, but if you handle the refresh in a single location in your event loop like...

    def input_handler(self):
        self.screen.refresh()
        ch = self.screen.getch()
        ...
    

    and remove the other calls to "refresh", the hide functionality functions properly