【问题标题】:Autocomplete bug in tkinter- HTML editortkinter- HTML 编辑器中的自动完成错误
【发布时间】:2021-08-16 19:28:26
【问题描述】:

我目前正在使用 Python tkinter 开发 HTML 编辑器应用程序。当您创建新项目或打开现有文件时,屏幕上会显示一个文本小部件,以及一个运行 HTML 代码的 Run 按钮。当您键入任何 HTML 开始标签时,脚本将立即向该元素添加一个结束标签(自动完成)。我正在使用一个名为get_stringvar 的函数,它受任何密钥释放的约束。该功能负责自动完成。当我键入我的第一个开始标签时,脚本会自动完成结束标签。但是当我输入我的第二个开始标签时,结束标签没有被自动完成。有人可以帮我解决这个问题吗?我的一些代码:

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter import messagebox
import webbrowser
import os

window = tk.Tk()
window.title("HTML Editor")
window.configure(bg="grey")
window.state("zoomed")
title = tk.Label(window, text="HTML Editor", font=("Arial Rounded MT Bold", 40, "underline"), bg="grey")
title.place(x=400, y=20)


def get_stringvar(event):
    content = text_box.get("1.0", tk.END)
    keys = ["Return", "Up", "Down", "Left", "Right"]

    if event.keysym in keys:
        return

    line = content.splitlines()[-1]
    if "/" not in line and line != "<!DOCTYPE html>":
        if ("<" in line and ">" in line) and line.index(">") + 1 == len(line):
            index = line.index("<")
            index2 = line.index(">") + 1
            new_line = "<" + "/" + line[index + 1:index2 - 1] + ">"
            text_box.insert(tk.END, new_line)
            line2 = content.splitlines().index(line) + 1
            text_box.mark_set("insert", "%d.%d" % (line2, index2))




create = tk.Button(window, text="Create a new file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
                   command=save_file)
create.place(x=420, y=200)
open_e = tk.Button(window, text="Open an existing file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
                   command=open_file)
open_e.place(x=420, y=350)

window.protocol("WM_DELETE_WINDOW", on_closing)
frame = tk.Frame(window, bd=2, relief="raised")

text_box = tk.Text(window, font=("Courier New", 10), fg="black")
text_box.bind("<KeyRelease>", get_stringvar)

scroll_bar = tk.Scrollbar(window, command=text_box.yview)

run_b = tk.Button(frame, text="Run", width=6, height=2, bg="white", command=run_code)

text_box.configure(yscrollcommand=scroll_bar.set)

window.mainloop()

更新代码(非常感谢@TheLizzard):

import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter import messagebox
import webbrowser
import os

window = tk.Tk()
window.title("HTML Editor")
window.configure(bg="grey")
window.state("zoomed")
title = tk.Label(window, text="HTML Editor", font=("Arial Rounded MT Bold", 40, "underline"), bg="grey")
title.place(x=400, y=20)


def get_stringvar(event):
    line = text_box.get("insert linestart", "insert")
    if (line[-1] == ">") and ("<" in line):
        new_line = "</" + line[line.rindex("<") + 1:-1] + ">"
        text_box.insert("insert", new_line)
        text_box.mark_set("insert", f"insert-{len(new_line)}c")
        return "break"

create = tk.Button(window, text="Create a new file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
                   command=save_file)
create.place(x=420, y=200)
open_e = tk.Button(window, text="Open an existing file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
                   command=open_file)
open_e.place(x=420, y=350)

window.protocol("WM_DELETE_WINDOW", on_closing)
frame = tk.Frame(window, bd=2, relief="raised")

text_box = tk.Text(window, font=("Courier New", 10), fg="black")
text_box.bind("<Tab>", get_stringvar)

scroll_bar = tk.Scrollbar(window, command=text_box.yview)

run_b = tk.Button(frame, text="Run", width=6, height=2, bg="white", command=run_code)

text_box.configure(yscrollcommand=scroll_bar.set)

window.mainloop()

【问题讨论】:

  • 你能做一个最小的工作示例吗?现在我们真的不需要 1/2 的代码,就像所有文件保存/打开的东西一样。
  • @TheLizzard,我会编辑一些没有问题的代码
  • 尝试绑定到"&lt;KeyRelease&gt;" 而不是"&lt;KeyPress&gt;"
  • @TheLizzard,还是不行
  • @TheLizzard,现在它可以工作了,即使我没有改变任何东西。

标签: python tkinter


【解决方案1】:

试试这个:

import tkinter as tk


def tab_pressed(event):
    line = text_box.get("insert linestart", "insert")
    if (line[-1:] == ">") and ("<" in line):
        new_line = "</" + line[line.rindex("<")+1:-1] + ">"
        text_box.insert("insert", new_line)
        text_box.mark_set("insert", f"insert-{len(new_line)}c")
        # Stop the tab from being added
        return "break"

    # Remove these 2 lines if you like tabs over spaces
    text_box.insert("insert", " "*4)
    return "break"


window = tk.Tk()

text_box = tk.Text(window)
text_box.bind("<Tab>", tab_pressed)
text_box.pack(side="left", fill="both", expand=True)

scroll_bar = tk.Scrollbar(window, command=text_box.yview)
scroll_bar.pack(side="left", fill="y")

text_box.configure(yscrollcommand=scroll_bar.set)

window.mainloop()

与其绑定到"&lt;KeyPress&gt;""&lt;KeyRelease&gt;",不如绑定到"&lt;Tab&gt;" 对用户更友好。此外,您的代码仅在用户写在最后一行时才有效。您应该使用"insert",而不是使用"end"。也请看this 它会对你有很大帮助。另外我的代码使用line.rindex("&lt;") 来获取line 中最右边的"&lt;" 的索引。

仅当用户按下"&lt;Tab&gt;" 时,上面的代码才会自动完成 html 标记。要测试它,只需输入&lt;aaa&gt;,然后按Tab(仅当光标在&gt; 之后才有效)。

【讨论】:

  • 非常感谢您提供详细且解释清楚的答案!绑定"&lt;Tab&gt;" 而不是"&lt;KeyRelease&gt;" 是个好主意。我被这个问题困扰了几个小时,这真的让我很难过。再次感谢您的帮助
  • @Roni 没问题,但我只知道这一点,因为我为 C++ 做了一个自动完成器:D
  • @Roni 顺便说一句,现在的 html 编辑器通常甚至不需要你输入 &lt;&gt; 只需输入标签名称,它会自动放置这些尖括号,但确保你也可以这样保留它跨度>
  • @Matiiss 我用记事本做网站...它没有那个功能。所以你是说,如果我输入:p,然后按 Tab,它会将其转换为 &lt;p&gt;|&lt;/p&gt;,其中 | 是光标?我可能会这样做。
  • @TheLizzard 你不会停止让我吃惊的,首先你使用 IDLE,这还不错,但是在这里你使用记事本编写 html(或记事本++?)还是自动完成全局?无论如何,是的,这至少是PyCharmVSCode 自动完成的方式,只需输入字母并按制表符,添加括号和结束标签。此外,对于某些标签,至少 PyCharm 会自动添加 src="|" 之类的属性,并将光标放在“”和其他一些东西之间,我的意思是,如果可以的话,你应该尝试一下,至少要获得功能
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 2013-05-14
  • 1970-01-01
相关资源
最近更新 更多