简体   繁体   English

Tkinter Text 小部件无法将“<”识别为单词的一部分

[英]Tkinter Text widget not recognizing "<" as part of a word

I'm trying to make a simple HTML Editor with Tkinter, with Python 3.10.我正在尝试使用 Tkinter 和 Python 3.10 制作一个简单的 HTML 编辑器。 Right now I'm trying to implement auto-completion using the Tkinter Text widget.现在我正在尝试使用 Tkinter Text 小部件实现自动完成。 The widget checks the word currently typed to see if it matches with any of the HTML tags in self._tags_list .小部件检查当前键入的单词,看它是否与self._tags_list中的任何 HTML 标记匹配。 And if it does, it auto-completes it.如果是这样,它会自动完成它。

Code:代码:

import random
import tkinter as tk


class IDE(tk.Text):
    def __init__(self, *args, **kwargs):
        tk.Text.__init__(self, *args, **kwargs)

        self._tags_list = ['<html></html>', '<head></head>', '<title></title>', '<body></body>', '<h1></h1>',
                           '<h2></h2>', '<h3></h3>', '<h4></h4>', '<h5></h5>', '<h6></h6>', '<p></p>', '<b></b>']

        self.bind("<Any-KeyRelease>", self._autocomplete)
        self.bind("<Tab>", self._completion, add=True)
        self.bind("<Return>", self._completion, add=True)

    def callback(self, word):
        # Returns possible matches of `word`
        matches = [x for x in self._tags_list if x.startswith(word)]
        return matches

    def _completion(self, _event):
        tag_ranges = self.tag_ranges("autocomplete")
        if tag_ranges:
            self.mark_set("insert", tag_ranges[1])
            self.tag_remove("sel", "1.0", "end")
            self.tag_remove("autocomplete", "1.0", "end")
            return "break"

    def _autocomplete(self, event):
        if event.keysym not in ["Return"] and not self.tag_ranges("sel"):
            self.tag_remove("sel", "1.0", "end")
            self.tag_remove("autocomplete", "1.0", "end")
            word = self.get("insert-1c wordstart", "insert-1c wordend")
            print(f"word: {word}")

            matches = self.callback(word)
            print(f"matches: {matches}")

            if matches:
                remainder = random.choice(matches)[len(word):]
                print(remainder)
                insert = self.index("insert")
                self.insert(insert, remainder, ("sel", "autocomplete"))
                self.mark_set("insert", insert)
                return


if __name__ == "__main__":
    window = tk.Tk()
    window.title("Autocomplete")
    window.geometry("500x500")
    text = IDE(window)
    text.pack(fill=tk.BOTH, expand=True)
    window.mainloop()

Used from @TRCK .@TRCK使用。 When I type in the "<" to start an HTML tag, it detects the first possible auto-completion (a random tag from self._tags_list minus the "<" at the beginning).当我输入“<”来启动 HTML 标记时,它会检测到第一个可能的自动完成( self._tags_list中的随机标记减去开头的“<”)。 However, when I type in a second character, it detects that character as a separate word and does not auto-complete.但是,当我输入第二个字符时,它会将该字符检测为单独的单词并且不会自动完成。 I've tested it with words not starting with "<" and it worked fine.我已经用不以“<”开头的单词对其进行了测试,并且效果很好。

For example, terminal output when I type "<h" into the widget:例如,当我在小部件中键入“<h”时的终端输出:

When I hit "<":当我点击“<”时:

word: <
matches: ['<html></html>', '<head></head>', '<title></title>', '<body></body>', '<h1></h1>', '<h2></h2>', '<h3></h3>', '<h4></h4>', '<h5></h5>', '<h6></h6>', '<p></p>', '<b></b>']
remainder: h3></h3>

When I add the "h":当我添加“h”时:

word: h
matches: []

Image of Tkinter window: Tkinter 窗口的图像:

窗户

Can someone please tell me why this is happening and how to fix it?有人可以告诉我为什么会发生这种情况以及如何解决吗? I've checked all around and found nothing yet.我查遍了周围,还没有发现任何东西。 Sorry if it is obvious, but I am now learning Tkinter.对不起,如果很明显,但我现在正在学习 Tkinter。 Also if there are any other problems in the code, please tell me.另外,如果代码中还有其他问题,请告诉我。

A word in wordstart is defined as wordstart中的一个词定义为

"a word is either a string of consecutive letter, digit, or underbar (_) characters, or a single character that is none of these types." “一个词要么是一串连续的字母、数字或下划线 (_) 字符,要么是不是这些类型的单个字符。”

when you type more characters after < , the wordstart starts from the character next to the < .当您在<之后键入更多字符时, wordstart<旁边的字符开始。 You can make this work by adding -1c at the end of wordstart您可以通过在-1c来完成这项工作

word = self.get("insert -1c wordstart -1c", "insert -1c wordend")

By adding通过添加

if "<" in word:
    word = word[word.index("<"):]

after word you can have a slight improvement. word后你可以有轻微的改善。

Besides that you also need to exclude BackSpace, Ctrl+a etc from your keysym除此之外,您还需要从键盘符号中排除 BackSpace、Ctrl+a 等

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM