[英]How do I implement a find and replace function in a tkinter Text widget?
I have the following code:我有以下代码:
def find_and_replace(self, *args):
findandreplace = tk.Toplevel(master)
findandreplace.title('Find & Replace')
find_label = tk.Label(findandreplace, text='Find')
find_label.pack(side = tk.LEFT)
find_words = tk.StringVar()
find_entry = tk.Entry(findandreplace, textvariable=find_words)
find_entry.pack(side = tk.LEFT, fill = tk.BOTH, expand = 1)
find_button = tk.Button(findandreplace, text='Find', command=self.find)
find_button.pack(side = tk.LEFT)
replace_label = tk.Label(findandreplace, text='Replace')
replace_label.pack(side = tk.LEFT)
replace_words = tk.StringVar()
replace_entry = tk.Entry(findandreplace, textvariable=replace_words)
replace_entry.pack(side = tk.LEFT, fill = tk.BOTH, expand = 1)
replace_button = tk.Button(findandreplace, text='Replace', command=self.replace)
replace_button.pack(side = tk.LEFT)
find_string = find_words.get()
replace_string = replace_words.get()
return find_string, replace_string
def find(self, *args):
self.textarea.tag_remove('found', '1.0', tk.END)
find_word = self.find_and_replace()[0]
if find_word:
idx = '1.0'
while True:
idx = self.textarea.search(find_word, idx, nocase=1,
stopindex=tk.END)
if not idx:
break
lastidx = '% s+% dc' % (idx, len(find_word))
idx = lastidx
self.textarea.tag_config('found', foreground='red')
def replace(self, *args):
self.textarea.tag_remove('found', '1.0', tk.END)
find_word = self.find_and_replace()[0]
replace_word = self.find_and_replace()[1]
if find_word and replace_word:
idx = '1.0'
while True:
idx = self.textarea.search(find_word, idx, nocase=1,
stopindex=tk.END)
if not idx:
break
lastidx = '% s+% dc' % (idx, len(find_word))
self.textarea.delete(idx, lastidx)
self.textarea.insert(idx, replace_word)
lastidx = '% s+% dc' % (idx, len(replace_word))
idx = lastidx
self.textarea.tag_config('found', foreground='green', background='yellow')
And I am using a menubar in a different class to access this:我正在使用不同类中的菜单栏来访问它:
edit_dropdown.add_command(label="Find",
command=parent.find)
edit_dropdown.add_command(label="Replace",
command=parent.find_and_replace)
So, find_and_replace()
creates a new tk.Toplevel
widget where I can access the find()
and replace()
functions.因此, find_and_replace()
创建了一个新的tk.Toplevel
小部件,我可以在其中访问find()
和replace()
函数。
However, when I press on the respective buttons, all I get is two more windows created.但是,当我按下相应的按钮时,我得到的只是创建了两个窗口。 I want to highlight the find_words
string and then have it replaced by the replace_words
string.我想突出显示find_words
字符串,然后将其替换为replace_words
字符串。
I feel I'm messing up by accessing variables of one method in another and in the opposite manner.我觉得我通过以另一种方式以相反的方式访问一种方法的变量而搞砸了。
The root of your problem are these lines:你的问题的根源是这些行:
find_word = self.find_and_replace()[0]
replace_word = self.find_and_replace()[1]
self.find_and_replace
creates the dialog. self.find_and_replace
创建对话框。 You don't want to be creating new dialogs.您不想创建新对话框。 Instead, you need to access the widgets in the current dialog.相反,您需要访问当前对话框中的小部件。 That means you need to save references to the widgets as instance attributes, and then use those instance attributes.这意味着您需要将小部件的引用保存为实例属性,然后使用这些实例属性。
Note: you can reduce the complexity by not using the textvariable
attribute.注意:您可以通过不使用textvariable
属性来降低复杂性。 You're just adding overhead since you aren't taking advantage of any features of the variable that you can't do by just calling the entry widget directly您只是增加了开销,因为您没有利用直接调用条目小部件无法实现的变量的任何功能
For example:例如:
def find_and_replace(self, *args):
...
self.find_entry = tk.Entry(findandreplace)
self.replace_entry = tk.Entry(findandreplace)
...
def replace(self, *args):
...
find_word = self.find_entry.get()
replace_word = self.replace_entry.get()
...
Something like this should do the trick:像这样的事情应该可以解决问题:
from tkinter import *
# to create a window
root = Tk()
# root window is the parent window
fram = Frame(root)
# Creating Label, Entry Box, Button
# and packing them adding label to
# search box
Label(fram, text ='Find').pack(side = LEFT)
# adding of single line text box
edit = Entry(fram)
# positioning of text box
edit.pack(side = LEFT, fill = BOTH, expand = 1)
# setting focus
edit.focus_set()
# adding of search button
Find = Button(fram, text ='Find')
Find.pack(side = LEFT)
Label(fram, text = "Replace With ").pack(side = LEFT)
edit2 = Entry(fram)
edit2.pack(side = LEFT, fill = BOTH, expand = 1)
edit2.focus_set()
replace = Button(fram, text = 'FindNReplace')
replace.pack(side = LEFT)
fram.pack(side = TOP)
# text box in root window
text = Text(root)
# text input area at index 1 in text window
text.insert('1.0', '''Type your text here''')
text.pack(side = BOTTOM)
# function to search string in text
def find():
# remove tag 'found' from index 1 to END
text.tag_remove('found', '1.0', END)
# returns to widget currently in focus
s = edit.get()
if (s):
idx = '1.0'
while 1:
# searches for desried string from index 1
idx = text.search(s, idx, nocase = 1,
stopindex = END)
if not idx: break
# last index sum of current index and
# length of text
lastidx = '% s+% dc' % (idx, len(s))
# overwrite 'Found' at idx
text.tag_add('found', idx, lastidx)
idx = lastidx
# mark located string as red
text.tag_config('found', foreground ='red')
edit.focus_set()
def findNreplace():
# remove tag 'found' from index 1 to END
text.tag_remove('found', '1.0', END)
# returns to widget currently in focus
s = edit.get()
r = edit2.get()
if (s and r):
idx = '1.0'
while 1:
# searches for desried string from index 1
idx = text.search(s, idx, nocase = 1,
stopindex = END)
print(idx)
if not idx: break
# last index sum of current index and
# length of text
lastidx = '% s+% dc' % (idx, len(s))
text.delete(idx, lastidx)
text.insert(idx, r)
lastidx = '% s+% dc' % (idx, len(r))
# overwrite 'Found' at idx
text.tag_add('found', idx, lastidx)
idx = lastidx
# mark located string as red
text.tag_config('found', foreground ='green', background = 'yellow')
edit.focus_set()
Find.config(command = find)
replace.config(command = findNreplace)
# mainloop function calls the endless
# loop of the window, so the window will
# wait for any user interaction till we
# close it
root.mainloop()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.