MinhazMurks
MinhazMurks

Reputation: 301

Python curses how to change cursor position with curses.setsyx(y,x)?

I am learning how to use curses and I am trying to create a simple program to start off. I am expecting this program to have a q printed in the top left corner always, then it prints the most recently pressed character in 1,1. But I'm not sure how to set the position of the cursor, which should be changed by using the curses.setsyx(y,x) function but it isn't working. Here is my program:

import curses
import sys,os

def screen_init(stdscr):
    stdscr.clear()
    stdscr.refresh()
    stdscr.scrollok(1)

    height, width = stdscr.getmaxyx()

    curses.start_color()
    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)

    while True:
            stdscr.addstr(0, 0, "q", curses.color_pair(1))
            key = stdscr.getch()
            stdscr.addstr(1, 1, chr(int(key)), curses.color_pair(1))
            if key == ord('q'):
                    break
            elif key == ord('p'):
                    curses.setsyx(3, 3)
                    curs_y, curs_x = curses.getsyx()
                    curses.doupdate()
                    stdscr.addstr(1, 1, "clicked! " + str(curs_x) + " " + 
str(curs_y), curses.color_pair(1))

    stdscr.refresh()
    curses.endwin()

def main():
    curses.wrapper(screen_init)

if (__name__ == "__main__"):
    main();

Any ideas on why it isn't doing anything? When I use getsyx() it gets 3, 3 but the cursor's true position doesn't change

Upvotes: 5

Views: 12687

Answers (3)

tinyhare
tinyhare

Reputation: 2401

stdscr.move(y, x) moves the stdscr’s cursor, which is used for output position of characters. (so you should use this one)

curses.setsyx(y,x) moves the newscr's cursor which is used for show the cursor on the screen.

How to use setsyx():

for i in range(10):
    # output i
    stdscr.addstr(f"{i} ")
    # refresh stdscr to newscr(not show on the screen)
    stdscr.noutrefresh()
    # move the cursor of newscr to (1,0)
    curses.setsyx(1,0)
    # show it 
    curses.doupdate()
    time.sleep(1)
    
stdscr.getch()

You will see the Number showed one by one, but the cursor always show at (1,0)

enter image description here

The normal refresh() call is simply noutrefresh() followed by doupdate(); but we need setsyx() in the middle, so call them separately.

Upvotes: 0

jcomeau_ictx
jcomeau_ictx

Reputation: 38422

you can use stdscr.getyx() and stdscr.move(y, x) instead.

Upvotes: 6

Thomas Dickey
Thomas Dickey

Reputation: 54475

setsyx and getsyx affect a special workspace-screen named newscr, which is used to construct changes sent to stdscr when you call refresh.

stdscr has its own position, which is not affected by those calls.

Upvotes: 3

Related Questions