【发布时间】:2014-02-12 01:58:53
【问题描述】:
是否可以使用tk 创建一个可以支持syntax highlighting、autocomplete 的text editor,甚至可以在以后扩展为特定语言的IDE?
我找到了tkinter 小部件,但不确定它是否支持?
我认为如果一个小部件可以在用户编写文本时对文本进行一些处理,那么它就可以用于此目的。
【问题讨论】:
是否可以使用tk 创建一个可以支持syntax highlighting、autocomplete 的text editor,甚至可以在以后扩展为特定语言的IDE?
我找到了tkinter 小部件,但不确定它是否支持?
我认为如果一个小部件可以在用户编写文本时对文本进行一些处理,那么它就可以用于此目的。
【问题讨论】:
当然。 tkinter 文本小部件非常强大。您提到的所有事情都可以完成,甚至更多。还可以实现代码折叠、嵌入图片、超链接、撤消等。
以下是对您可能会有所帮助的相关问题的一些答案:
【讨论】:
Tkinter 应该是Python 到tk 的接口,所以我应该期望tk widgets 之一中的这些功能,或者通过组合@987654329 已经添加了强大的部分@与python
不要重复,因为 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"
【讨论】:
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()
【讨论】: