Reputation: 796
Can anyone answer why in the code below the command self.text.mark_previous(self.text.index("insert"))
works and returns the correct mark but self.text.mark_previous("insert")
returns tk::anchor1
instead? Just click on an area in the text and hit the button.
import tkinter as tk
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.text = tk.Text()
self.text.pack()
self.strings = ["Region 1", "Region 2", "Region 3"]
for text in self.strings:
self.text.mark_set(text, "insert")
self.text.mark_gravity(text, "left")
self.text.insert("insert", "{}\n".format(text))
for mark in self.strings:
print(self.text.index(mark))
self.button = tk.Button(text="Find Region", command=self.find_region)
self.button.pack()
def find_region(self):
self.text.update_idletasks()
region = self.text.mark_previous("insert") # This doesn't work. It returns tk::anchor1
region2 = self.text.mark_previous(self.text.index("insert")) # This works
print("You are in region {} {}".format(region, region2))
if __name__ == '__main__':
main = Main()
main.mainloop()
Upvotes: 1
Views: 394
Reputation: 385980
The answer is that tkinter doesn't consider "insert"
and index("insert")
as precisely the same thing when dealing with marks. They are the same from the perspective of just the text, but not from the perspective of all of the other data managed by the text widget.
Consider a text widget with the text "Hello, world" at line 1. When you click on the letter "w", a couple of things happen: tkinter will add the marks "insert", "tk::anchor1", and "current". These marks are ordered. If we were to convert the text widget contents to xml it might look something like this:
<text index='1.0'>Hello, </text>
<mark index='1.7' id='current'/>
<mark index='1.7' id='tk::anchor1'/>
<mark index='1.7' id='insert'/>
<text index='1.7'>world</text>
When calling mark_previous("1.7")
, the index "1.7" refers to the point immediately before the letter "w" and after all of the marks. Thus, when you ask for the previous mark, it's going to return "insert" since that is what is immediately to the left of the letter "w". However, if you ask for the mark previous to "insert" rather than "1.7", you're going to get "tk::anchor1" since that is the mark immediately to the left of the "insert" mark.
You can see the order of marks and data by using the text widget dump
method. It returns information as a list rather than xml, but it lets you see the internal structure of the document.
Continuing with the same example ("Hello, world", after clicking before the "w"), the dump
method returns the following (I've added newlines for clarity):
[
('text', 'Hello, ', '1.0'),
('mark', 'current', '1.7'),
('mark', 'tk::anchor1', '1.7'),
('mark', 'insert', '1.7'),
('text', 'world\n', '1.7')
]
As you can see, the mark "current" comes before the mark "tk::anchor1", which comes before the mark "insert", which comes before the letter "w" in "world".
Upvotes: 1
Reputation: 2554
tk::anchor#
at the same index as insert
, but on previous position.Initially or whenever the mouse pointer is not on any text, current
and insert
mark are at the same index and in the sequence of current
followed by insert
.
So if you click on your button "Find Region" at the start of program it will print,
You are in region current Region 3
because by sequence, current
mark is at previous position to insert
mark(but at same index), but Region 3
mark is at previous "index" to insert
mark.
From what I understand, tkinter adds an extra mark tk::anchor#
when you click in the textbox for first time(I don't know reason yet), which is at the same index as insert
but right before insert
mark(and after current
if mouse pointer not on text).
So when you search for previous mark based on name of mark and not index, then the previous mark on the same index will be returned. You can test it yourself by adding two user defined marks at the same index.
Upvotes: 2