Search code examples
pythonpositioncursortextfieldpysimplegui

PySimpleGUI: Set and get the cursor position in a multiline widget?


Is there a way to get the position of the cursor in a multiline widget in PySimpleGUI, storing it and putting the cursor back again on a defined position in the text of that widget?

Below you see the code I wrote so far. My aim is that when "jk" in typed in the upper window then the cursor goes down to the input line (that works). There the user can write a command and finish the input pressing (that I have not done yet).

The question is now how to make the cursor jump back in the upper window on the same position where it was before?!

import PySimpleGUI as sg

layout = [  [sg.Multiline(key = 'editor',
                          size = (50, 10), 
                          focus = True, 
                          enable_events = True)],
            [sg.InputText(key ='command', size = (45, 1), ),], ]

window = sg.Window('editor', layout)

while True:
    event, values = window.read()

    if 'jk' in values['editor']:
        # delete jk and jump down in the command line #
        window['editor'].update(values['editor'].replace('jk', ''))
        window.Element('command').SetFocus(force = True)
        
    if event in ('Close Window', None): 
        break
    
window.close()

Any help is appreciated as the is no documentation about setting or getting cursor position in PySimpleGui. Thanks in advance!


Solution

  • Tkinter code required here.

    • Using method deleteof tkinter Text widget, element.widget, to remove the input jk.
      • 'insert' is the position of the insertion cursor in the text widget.
      • 'insert-2c' step back 2 characters, with 'insert' it mark the area to delete.

    delete(index1, index2=None) Deletes text starting just after index1. If the second argument is omitted, only one character is deleted. If a second index is given, deletion proceeds up to, but not including, the character after index2. Recall that indices sit between characters.

    • Method set_focus of element sets the current focus to be on this element.

    • Method mark_set of the Text widget to set the position of insert cursor.

    mark_set(mark, index)

    If no mark with name mark exists, one is created with tk.RIGHT gravity and placed where index points. If the mark already exists, it is moved to the new location. This method may change the position of the tk.INSERT or tk.CURRENT indices.

    • chapter 24.1 Text widget indices show the wat to specify a position in the content of a Text widget or Multiline element.

    Refer: https://tkdocs.com/shipman/tkinter.pdf

    Example code show how it work, "jk" to jump from "M1" to "M2", and key to jump back from "M2" to "M1".

    import PySimpleGUI as sg
    
    sg.theme("DarkBlue")
    sg.set_options(font=('Courier New', 16))
    
    layout = [
        [sg.Multiline('', size=(40, 5), enable_events=True, key='M1')],
        [sg.Multiline('', size=(40, 5), key='M2')],
    ]
    window = sg.Window("Title", layout, finalize=True)
    
    m1, m2 = window["M1"], window['M2']
    m2.bind("<Return>", "_Return")
    
    while True:
        event, values = window.read()
        if event == sg.WINDOW_CLOSED:
            break
        elif event == "M1" and 'jk' in values["M1"]:
            m1.Widget.delete("insert-2c", "insert")
            m2.set_focus()
        elif event == "M2_Return":
            m1.set_focus()
        print(event, values)
    
    window.close()