如何在程序运行时向 EasyGUI 文本框中写入?

在使用 EasyGUI 库接收用户输入的脚本中,如果想要在程序运行时将进度、每个操作或函数的执行结果打印到文本框中,该怎么做?

2、解决方案

虽然 EasyGUI 本身不提供这样的功能,但是可以创建一个单独的 Tkinter 窗口,使用改进版代码来将输出行显示出来。具体方法如下:

(1)导入必要的库

import sys
import thread
import subprocess
import Queue
from Tkinter import BOTH, END, Frame, Text, TOP, YES
import tkFont

(2)创建 OutputPipe 类

class OutputPipe(object):
    def __init__(self, name=''):
        self.lock = thread.allocate_lock()
        self.name = name

    def __getattr__(self, attr):
        if attr == 'pipe':
            command = '"%s" "%s" "%s" "%s"' % (sys.executable, __file__, os.path.basename(sys.argv[0]), self.name)
            try:
                self.pipe = subprocess.Popen(command, bufsize=0,
                                             stdin=subprocess.PIPE,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE).stdin
            except Exception:
                exc_type, exc_value, exc_traceback = sys.exc_info()
                msg = ('%r exception in %s\n' %
                       (exc_type.__name__, os.path.basename(__file__)))
                with open('exc_info.txt', 'wt') as info:
                    info.write('msg:' + msg)
                    traceback.print_exc(file=info)
                sys.exit('fatal error occurred spawning output process')

        return super(OutputPipe, self).__getattribute__(attr)

    def write(self, data):
        with self.lock:
            self.pipe.write(data)

(3)定义队列和 Tkinter 应用程序

queue = Queue.Queue(100)

class Application(Frame):
    def __init__(self, master=None, font_size=8, text_color='#0000AA', rows=25, cols=100):
        Frame.__init__(self, master)
        title = "Output Stream from %s" % (sys.argv[1],)
        self.master.title(title)
        self.pack(fill=BOTH, expand=YES)
        font = tkFont.Font(family='Courier', size=font_size)
        width = font.measure(' '*(cols+1))
        height = font.metrics('linespace')*(rows+1)
        self.configure(width=width, height=height)
        self.pack_propagate(0)
        self.logwidget = Text(self, font=font)
        self.logwidget.pack(side=TOP, fill=BOTH, expand=YES)
        self.logwidget.bind('<Key>', lambda x: 'break')
        self.logwidget.bind('<Control-c>', lambda x: None)
        self.logwidget.configure(foreground=text_color)
        self.after(200, self.start_thread, ())

    def start_thread(self, _):
        thread.start_new_thread(read_stdin, (self,))
        self.after(200, self.check_q, ())

    def check_q(self, _):
        log = self.logwidget
        log_insert = log.insert
        log_see = log.see
        queue_get_nowait = queue.get_nowait
        go = True
        while go:
            try:
                data = queue_get_nowait()
                if not data:
                    data = '[EOF]'
                    go = False
                log_insert(END, data)
                log_see(END)
            except Queue.Empty:
                self.after(200, self.check_q, ())
                go = False

(4)创建 OutputPipe 对象并重定向标准输出流

sys.stderr = OutputPipe('stderr')
sys.stdout = OutputPipe('stdout')

(5)在函数中打印输出
使用 sys.stdout.write(data)sys.stderr.write(data) 来打印输出。

(6)运行应用程序
在需要显示输出的脚本中,导入 errorwindow 模块并创建一个 Application 对象,然后调用 mainloop() 方法即可。

app = Application()
app.mainloop()

这样,就可以在程序运行时将进度、每个操作或函数的执行结果打印到文本框中。