<blockquote>
<p>it isn't responding to commands</p>
</blockquote>
<p>它不响应命令的原因是您没有将<code>Text</code>小部件(<code>self.ttyText</code>)链接到<code>stdin</code>。当前,当你输入时,它会将文本添加到小部件中,而不添加其他内容。这种链接可以类似于您已经使用<code>stdout</code>和<code>stderr</code>完成的操作。在</p>
<p>在实现这一点时,您需要跟踪小部件中文本的哪一部分是用户输入的文本—这可以使用标记(<a href="https://www.tutorialspoint.com/python/tk_text.htm" rel="nofollow noreferrer">as described here</a>)来完成。在</p>
<blockquote>
<p>the thread doesn't stop when the user closes the window.</p>
</blockquote>
<p>我不认为没有一个“干净”的方法来解决这个问题而不需要重写主要的代码,但是一个似乎足够好的解决方案是它只需检测小部件何时被破坏并将字符串<code>"\n\nexit()"</code>写入解释器。这将调用解释器中的<code>exit</code>函数,这将导致对<code>shell.interact</code>的调用完成,从而使线程完成。在</p>
<p>在这里,不使用ado对代码进行了进一步修改:</p>
<pre><code>import tkinter as tk
import sys
import code
from threading import Thread
import queue
class Console(tk.Frame):
def __init__(self, parent, _locals, exit_callback):
tk.Frame.__init__(self, parent)
self.parent = parent
self.exit_callback = exit_callback
self.destroyed = False
self.real_std_in_out = (sys.stdin, sys.stdout, sys.stderr)
sys.stdout = self
sys.stderr = self
sys.stdin = self
self.stdin_buffer = queue.Queue()
self.createWidgets()
self.consoleThread = Thread(target=lambda: self.run_interactive_console(_locals))
self.consoleThread.start()
def run_interactive_console(self, _locals):
try:
code.interact(local=_locals)
except SystemExit:
if not self.destroyed:
self.after(0, self.exit_callback)
def destroy(self):
self.stdin_buffer.put("\n\nexit()\n")
self.destroyed = True
sys.stdin, sys.stdout, sys.stderr = self.real_std_in_out
super().destroy()
def enter(self, event):
input_line = self.ttyText.get("input_start", "end")
self.ttyText.mark_set("input_start", "end-1c")
self.ttyText.mark_gravity("input_start", "left")
self.stdin_buffer.put(input_line)
def write(self, string):
self.ttyText.insert('end', string)
self.ttyText.mark_set("input_start", "end-1c")
self.ttyText.see('end')
def createWidgets(self):
self.ttyText = tk.Text(self.parent, wrap='word')
self.ttyText.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
self.ttyText.bind("<Return>", self.enter)
self.ttyText.mark_set("input_start", "end-1c")
self.ttyText.mark_gravity("input_start", "left")
def flush(self):
pass
def readline(self):
line = self.stdin_buffer.get()
return line
if __name__ == '__main__':
root = tk.Tk()
root.config(background="red")
main_window = Console(root, locals(), root.destroy)
main_window.mainloop()
</code></pre>
<p>除了解决问题中所述问题的代码外,此代码几乎没有更改。在</p>
<p>与我之前的回答相比,这段代码的优点是它可以在单个进程中工作,因此可以在应用程序的任何一点创建,从而给程序员更多的控制权。在</p>
<p>{I不应该有一个基本的文本输出}和其他可编辑文本}的输出</p>