【问题标题】:Using tk to create a text editor使用 tk 创建文本编辑器
【发布时间】:2014-02-12 01:58:53
【问题描述】:

是否可以使用tk 创建一个可以支持syntax highlightingautocompletetext editor,甚至可以在以后扩展为特定语言的IDE

我找到了tkinter 小部件,但不确定它是否支持?

我认为如果一个小部件可以在用户编写文本时对文本进行一些处理,那么它就可以用于此目的。

【问题讨论】:

    标签: text tkinter editor tk


    【解决方案1】:

    当然。 tkinter 文本小部件非常强大。您提到的所有事情都可以完成,甚至更多。还可以实现代码折叠、嵌入图片、超链接、撤消等。

    以下是对您可能会有所帮助的相关问题的一些答案:

    【讨论】:

    • Tkinter 应该是Pythontk 的接口,所以我应该期望tk widgets 之一中的这些功能,或者通过组合@987654329 已经添加了强大的部分@与python
    • @yassin:我很抱歉。通常当有人在 python 问题中提到 tk 时,我假设他们在谈论 tkinter。我没有意识到你在谈论实际的 tk 库。是的,当您使用 tkinter 时,您已经获得了 tk 的所有功能。 tkinter 不是小部件,它是所有 tk 小部件的包装器。所以,你可以用 tk 做的几乎所有事情都可以用 tkinter 做。
    【解决方案2】:

    不要重复,因为 Bryan Oakley 已经回答了这个问题,但是是的。他是对的。文本小部件非常强大。我从未见过另一个与其功能广度相匹配的文本小部件。

    Tkinter 是我发现的用于制作文本编辑器的最方便的 GUI 库。事实上,我自己已经做了一段时间了。您有兴趣制作一款还是正在寻找一款已经使用 Tkinter 制作的?

    对我来说,语法高亮和自动完成并不是文本编辑器中最重要的功能。我更关心快速/方便的文件/项目访问、启动/编译/运行程序、Unicode 或特殊字符输入、小部件颜色方案、导航键绑定、选项卡,以及为我喜欢的各种狂野工具提供各种快捷方式让我的生活更轻松(也更有趣)。所以,实际上我现在才刚刚开始语法高亮(在完成了大部分其他工作之后)。但是,是的,语法高亮可以在 Tkinter 中完成。

    实际上,您可能希望在文本编辑器中获得的许多功能甚至不需要与 GUI 库做太多的事情。例如,让它识别您正在编辑的文件类型,这样您就可以使用正确的程序运行您的文件(或使用正确的编译器对其进行编译)。这与 Tkinter 关系不大。

    如果您想实时聊聊文本编辑器,请告诉我。

    Python 自带的 IDE IDLE 好像也是用 Tkinter 写的。查看源代码有时会有所帮助,但他们倾向于以与我个人推荐的方式不同的方式做事,尽管我确信有些人更喜欢它而不是我喜欢的方式。

    Tkinter 有一些缺点,但就我的目的而言,它们比我在其他 GUI 库中看到的缺点要好。有些事情需要更多的工作,但大多数似乎也提供了更多的灵活性。有些事情也需要更少的工作。令人印象深刻的是,Tkinter 似乎没有很多错误,并且大多数存在的错误都可以编程。它相当健壮。有时,因为没有原生小部件并且没有以某种方式呈现字体,但不要听别人的,它会得到一个坏名声。小部件很好,无论它们是否是原生的,而且字体看起来很棒。如果字体有问题,我想他们已经解决了。如果我错了,请告诉我。我的看起来很完美(就像他们在 LibreOffice 中所做的那样,如果不是更好的话)。此外,不应忽视 Tkinter 的好处。 Tkinter 很棒。

    Python 的 help() 方法将成为您的朋友。在类和模块上使用它。

    Tkinter 的一大优点是它几乎随 Python 一起提供。因此,不像 WxPython(它甚至不在 3.x 上,尽管他们正在用另一个名字为它做一些东西),Tkinter 很可能会自动支持所有未来的 Python 版本(直到如果/当他们决定用别的东西代替它——我不知道他们会不会,除非他们发现了一些非常棒的东西)。另外,下载量不是很大。

    无论如何,要开始使用,您需要了解标记(尤其是内置标记)和标签。您可能会大量使用它们来做很多事情。这些对于访问小部件中的特定文本区域并对其执行操作非常重要。

    INSERT 是一个字符串,'insert'。但是,这也是一个标记。标记是标记位置的变量索引。 'insert' 标记代表文本小部件中插入文本的索引。文档的开头是索引"1.0" 而不是"0.0"1 是第 1 行。0 是字符 0。我不相信开头有标记。您只需使用索引。结束的标记是 END(它是一个字符串,'end')。 'sel.first' 和 'sel.last' 表示所选文本开头和结尾的索引。 SEL(或'sel')是一个标签。标签有点像 HTML 标签,它们标记事物的开始和结束(以及介于两者之间的所有文本)。您可以制作自己的标签来添加文本样式(如粗体和斜体,或者只是突出显示,这对于语法突出显示很有用)。您可以检查一系列文本以查看它是否具有特定标签。例如,

    SEL in self.myTextWidget.tag_names(INSERT)
    

    如果选择了文本插入之后(即 at)的字符,将返回 True

    对于标记,您可以使用一些方便的符号来获取一些方便的索引位置。例如"insert wordstart" 将为您提供'insert' 标记所在单词的开头索引。 "insert+2c" 会给你插入后两个字符的位置。不管怎样,这样的东西很多。

    如果您正在制作跨平台应用程序,您会想知道一些事件在不同平台上是不同的。因此,请检查并确保它们都能正常工作。

    您还需要意识到,尽管文本小部件中的某些标准键盘快捷键不起作用(例如 Control-a 不会全选),但实际上有快捷键。它们只是不同的捷径。但是,您可以覆盖它们并轻松制作自己的:

        …
        #We're doing both a and A to make sure it works properly when caps-lock is on.
        #Control-Shift-a is different from Control-A despite how it may seem.
        self.myTextWidget.bind("<Control-a>", self.select_all)
        self.myTextWidget.bind("<Control-A>", self.select_all)
    
    def select_all(self, event):
        self.myTextWidget.tag_add("sel", "1.0", "end-1c") #END actually goes beyond the end of the text, adding a new line (so, I subtract a character).
        return "break" #If you want to override the default binding, you need to return "break"
    

    【讨论】:

    • Idle 肯定使用 tkinter。语法高亮是通过一个复杂的正则表达式和 idlelib.Colordelegator 中的标签来完成的。如果您想复制任何 idlelib 代码,请复制它,因为 API 基本上是私有且未记录的。
    • 我是一个相对较新的空闲维护者,对现在的工作方式没有特别的兴趣。虽然我不打算重写 Idle,但我对如何以不同方式完成某些事情的想法感兴趣,也许更好(个人资料上的电子邮件)。
    • 我应该注意,在 Tkinter 中手动进行语法高亮显示,虽然我的想法是可能的,但结果却使编辑器变得相当慢。我很好奇 Idle 是如何做到这么快的。我想我会编辑我的答案。
    • @TerryJanReedy 太棒了!很高兴听到参与维护 Idle 的人的来信。我看不到通过您的个人资料向您发送电子邮件的方法。您可以通过此电子邮件表格给我发电子邮件,然后我们可以协商。 foxyform.com/form.php?id=336939&sec_hash=6d22434949a
    【解决方案3】:

    Tkinter 相当灵活,它可以用来独立完成许多任务。实际上,我已经在 python 2.7 中使用 tkinter 制作了自己的迷你文本编辑器。虽然它还没有高级功能。但我认为这将是你想法的一个很好的基础。确保你已经安装了 python2.7。

    from Tkinter import * 
    import tkFileDialog
    
    class Files(Frame):
    
        def __init__(self, parent):
            Frame.__init__(self, parent)   
    
            self.parent = parent        
            self.initUI()
    
        def initUI(self):
    
            self.parent.title("File dialog")
            self.pack(fill=BOTH, expand=1)
    
            menubar = Menu(self.parent)
            self.parent.config(menu=menubar)
    
            fileMenu = Menu(menubar)
            fileMenu.add_command(label="Save", command = self.save_command)
            fileMenu.add_command(label="Open", command = self.onOpen)
            menubar.add_cascade(label="File", menu=fileMenu)        
    
            self.txt = Text(self)
            self.txt.pack(fill=BOTH, expand=1)
    
    
        def onOpen(self):
    
            ftypes = [('Python files', '*.py'), ('All files', '*')]
            dlg = tkFileDialog.Open(self, filetypes = ftypes)
            fl = dlg.show()
    
            if fl != '':
                text = self.readFile(fl)
                self.txt.insert(END, text)
    
        def readFile(self, filename):
    
            f = open(filename, "r")
            text = f.read()
            return text
    
        def save_command(self):
            file = tkFileDialog.asksaveasfile(mode='w')
            if file != None:
                    data = self.txt.get('1.0', END+'-1c')
                    file.write(data)
                    file.close()
    
    
    root = Tk()
    
    top = Frame(root)
    top.pack(fill=BOTH, expand=1)
    
    def build():
        l = Label(top, text="test phrase")
        l.pack(side="left")
        ent = Entry(top)
        ent.pack(side="left")
    
    bottom = Frame(root)
    bottom.pack()
    
    ex = Files(root)
    ex.pack(side="bottom")
    
    root.geometry("300x250+300+300")
    root.mainloop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 2012-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多