Python tkinter Text INSERT CURRENT Cursor [duplicate] - python

This question already has an answer here:
Why Text cursor coordinates are not updated correctly?
(1 answer)
Closed 7 years ago.
I write a simple program with tkinter Text, and bind arrow down key with a function but the CURRENT and INSERT cursor is not correct when I press the down key.
Firstly, CURRENT sometimes is not updated, and sometimes is updated with wrong index
Secondly, INSERT is always updated, however its index is the last position, for example, if current index is line 1 column 1, then I press Down key, the printed result is still 1.1(line 1 column 1), but my cursor has already come to line 2.
Anyone has any experience on that? Thanks in advance!
def tipKeyDown(event):
pos=text.index(CURRENT)
print(pos)
pos=text.index(INSERT)
print(pos)
text = Text(textFrm, relief=SOLID)
text.bind('<Button-1>', tipButton1)
text.bind('<Down>', tipKeyDown)

You can use KeyRelease which is raised after the text change.
text.bind('<KeyRelease-Down>', tipKeyDown)
BTW, CURRENT is corresponds to the character closest to the mouse pointer. (not related to insertion cursor)

This has to do with the order that tkinter processes events. The short answer is, custom bindings on widgets are processed before the default bindings, and it's the default bindings that cause the text to be inserted or deleted, the index changed, etc.
See more here: Basic query regarding bindtags in tkinter and How to bind self events in Tkinter Text widget after it will binded by Text widget? and Why Text cursor coordinates are not updated correctly?

Related

tkinter insert and delete function

I have started experimenting with tkinter a little. Right now im trying to build a simple calculator and for that I used the delete and insert function to clear the Entry.
This is the command I used:
t1.delete(1.0, 'end')
My question: What is the meaning of '1.0' and the 'end'?
Tkinter Text widget has delete(first, last=None) method to delete the characters at the index of first, or within the range of (first, last) from the text box.
Visit this link: what is the meaning of '1.0' and the 'end'

How to move the insertion cursor of a tkinter text widget to a certain index

I want to move the insertion cursor(caret)(|) within the tkinter text widget, to a certain text widget indice.
USE CASE:
I am making an autocomplete program wherein if I type one single apostrophe(quotation mark), the other one automatically is inserted into the text widget, which I got working all fine. But after, the second apostrophe is generated I want to bring the insertion cursor(caret), in the middle of the two apostrophes rather than at the end. Like so -:
One apostrophe typed(inside the tkinter text widget) -:
'[insertion cursor(caret)(|)]
The other one is auto-inserted pushing the insertion cursor(caret) to the end(The code till this part has been figured out by me successfully.) -:
''[insertion cursor(caret)(|)]
The insertion cursor(caret) shifts between the two apostrophes(The objective of this question.) -:
'[insertion cursor(caret)(|)]'
NOTE: These operations are all taking place within a tkinter text widget.
You call the mark_set method, using "insert" as the name of the mark.
the_widget.mark_set("insert", "4.0") will set the insertion cursor at the start of the fourth line. You can use the_widget.mark_set("insert", "insert-1c") to move the cursor back one character.
Here is an example of one way for automatically inserting a closing parenthesis or bracket. In this example, the code inserts both the opening and closing character so it returns "break" to prevent the default behavior provided by the text widget.
import tkinter as tk
def autocomplete(widget, first, last):
# insert the two characters at the insertion point
widget.insert("insert", first + last)
# move insertion cursor back one character
widget.mark_set("insert", "insert-1c")
# prevent the text widget from inserting the character that
# triggered the event since we've already inserted it.
return "break"
root = tk.Tk()
text = tk.Text(root, wrap="word")
text.pack(fill="both", expand=True)
text.bind("(", lambda event: autocomplete(event.widget, "(", ")"))
text.bind("[", lambda event: autocomplete(event.widget, "[", "]"))
root.mainloop()

How to get current cursor position for Text widget

I am using an onscreen keyboard to type data for a tkinter based gui.
I was able to use the entry field to enter, edit data through the onscreen keyboard such as getting current cursor position and length of the string.
temp = self.entry_label.get()
length_string=len(temp)
cursor_position = self.entry_label.index(INSERT)
But I wish to do the same for a Text widget. I could get the text for Text widget using get() method and its length but cannot get the current mouse cursor position.
temp=self.new_text.get(1.0, END)
cursor_position = self.new_text.index(INSERT)
Acutally it works and i am able to add character to that poisition , but after adding character cursor goes back to origional position , i.e last character
maybe This works? Else maybe text_widget.index(Tkinter.INSERT) is what should work.
Although the other answer is correct and worked I believe tk.Current is the meta answer.
"tk.INSERT"
as provided by this reference.
https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/text-index.html

Formatting text while typing in a Tkinter Text widget

I'm trying to add notes to a given text that's not to be altered. It's pretty much like formatting in common text editors.
I have tried to get the current cursor position via .index('insert'), and then tag the character either forwards with tag_add(current cursor, current cursor '+1c'), or backwards with tag_add(current cursor + '-1c', current cursor). This results in tagging either the character right before or after the character just typed.
Are there any workarounds to live-tag the actually typed character?
import tkinter
main = tkinter.Tk()
def typing(event):
text.tag_configure('note', background='yellow')
text.tag_configure('note2', background='blue')
cur_cursor = text.index("insert")
text.tag_add('note', cur_cursor + '-1c', cur_cursor)
text.tag_add('note2', cur_cursor, cur_cursor + '+1c')
text = tkinter.Text(main)
text.grid()
text.bind('<Key>', typing)
for i in ['OX'*20 + '\n' for i in range(10)]:
text.insert('end', i)
main.mainloop()
Edit: Although Bryan's answer worked for me you might get problems with fast typing as described here: how-to-get-cursor-position
The simplest solution is to bind on <KeyRelease> rather than <Key>. The reason is that the text widget doesn't actually insert the character you typed until its own <Key> binding fires, and that binding always fires after any custom bindings you have on the widget.

Recovering checkboxes in python Tkinter

I have a situation in which i create a few checkboxes and a 'save' button on a frame. Clicking on the button will save the current 'check status' of the checkboxes and close the frame (the frame has another frame as it's parent). The 'check status' is stored in a list in a separate .py file.
There's another button, clicking on which would i would want to restore those same check values on the check boxes. I am not sure what approach is proper here: whether to save the checkbox objects itself and load them or to create new checkboxes every time and apply the check status values on them.
This issue has taken up quite some time of mine as i am new to the python GUI concept, any help would be much appreciated.
P.S: if any details are required to make the question more clear kindly let me know.
EDIT: here's a small representation of what i have tried:
#file that generates the checkboxes (part of a bigger code)
var_list=[] #list of the variables of the checkbox objects
load_status = savedata.load() #fetch the saved status list from another file, if it exists
if len(load_status)!=0: #if the checkboxes have already been created before
for count in range(len(var_list)):
if load_status[count] == 0:
var_list[count].set(0) #set/apply the values from the status list
else:
var_list[count].set(1)
return
def check(var_list):
check_status_list=[]
for i in range(len(var_list)):
c = var_list[i].get()
check_status_list.append(c) #the status of the checkboxes that is stored in another file
var = IntVar()
var_list.append(var)
poll_check = ttk.Checkbutton(parent,variable=rr,command=lambda:check(var_list))
poll_check.place(x=x1,y=y1)
x1=x1+15
when i click on the save button the status list (check_status_list) is stored in another file. On clicking the third button ('load') i fetch the status list first and (try to) set the values on the already exsting checkbox objects.
Kindly feel free to point out the (obviously) silly mistake that this approach has.

Categories