我一直在尝试创建自己的基本Python IDE。我创建了一个界面,其中包含一个允许我输入语法的输入文本框和一个显示Python解释器的结果输出的pmw.ScrolledText。
我真正希望做的是将这两个小部件组合成一个可以处理输入和输出的小部件。我没有找到任何这样的小部件,但我相当确定有可能以某种方式这样做,因为Idle是用Tk编写的,它基本上就是我在我的应用程序中寻找的东西。查看Idle源代码并没有真正向我展示这样做的简洁方法。
基本上我正在寻找类似于pmw.ScrolledText的东西,它接受输入并且还可以显示输出。
我只是想知道这是否有可能与Tk以及可能采取的任何想法使其发挥作用。
感谢。
答案 0 :(得分:2)
这绝对有可能。文本小部件是您要使用的,但是您必须进行一些编码来处理显示提示,然后在用户点击返回键时执行操作。
我认为最简单的方法是在插入提示后立即设置标记,然后当您检测到返回键时,从该标记中获取所有内容作为要运行的命令。
这是一个说明该技术的简短示例。它并不完美(例如,您可以删除提示),但它显示了一般的想法。
import Tkinter as tk
class Application(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.text = tk.Text(self, wrap="word", height=20)
self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)
self.text.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.text.pack(side="left", fill="both", expand=True)
self.text.bind("<Return>", self.process_input)
self.prompt = ">>> "
self.insert_prompt()
def insert_prompt(self):
# make sure the last line ends with a newline; remember that
# tkinter guarantees a trailing newline, so we get the
# character before this trailing newline ('end-1c' gets the
# trailing newline, 'end-2c' gets the char before that)
c = self.text.get("end-2c")
if c != "\n":
self.text.insert("end", "\n")
self.text.insert("end", self.prompt, ("prompt",))
# this mark lets us find the end of the prompt, and thus
# the beggining of the user input
self.text.mark_set("end-of-prompt", "end-1c")
self.text.mark_gravity("end-of-prompt", "left")
def process_input(self, event=None):
# if there is an event, it happened before the class binding,
# thus before the newline actually got inserted; we'll
# do that here, then skip the class binding.
self.text.insert("end", "\n")
command = self.text.get("end-of-prompt", "end-1c")
self.text.insert("end", "output of the command '%s'...!" % command)
self.text.see("end")
self.insert_prompt()
# this prevents the class binding from firing, since we
# inserted the newline in this method
return "break"
root = tk.Tk()
root.wm_geometry("400x100")
app = Application(root).pack(side="top", fill="both", expand=True)
root.mainloop()