在 GUI 的 window 中显示 CMD 控制台 - PySimpleGUI

display the CMD console in a window in GUI - PySimpleGUI

我正在使用 PySimpleGUI 创建一个 GUI,并希望有一个框架来显示程序中所有函数的输出打印(如在 cmd 控制台中)。 我尝试使用(相关代码行):

def hello():
    print('hello')

layout = [[sg.Frame("Output console", [[sg.Text(" ", size=(0, 1), key='-OUTPUT-')]])]]
window['-OUTPUT-'].update(hello())

我可以在控制台中看到打印,但在 GUI 的框架中看不到。 我该怎么做?

要像在 CMD 控制台中一样显示输出,您应该使用 sg.Multiline,而不是 sg.Text,它只是一个标签。

要重定向 stdout 和 stderr 的输出,设置选项 reroute_stdout=Truereroute_stderr=True,同时设置选项 autoscroll=True 以在元素末尾添加更多数据时自动滚动。

演示代码 - GUI 将仅更新回 window.read

import PySimpleGUI as sg

def hello():
    print('hello')

frame_layout = [[sg.Multiline("", size=(80, 20), autoscroll=True,
    reroute_stdout=True, reroute_stderr=True, key='-OUTPUT-')]]

layout = [
    [sg.Frame("Output console", frame_layout)],
    [sg.Push(), sg.Button("Say Hello")],
]
window = sg.Window("Title", layout, finalize=True)

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break
    elif event == "Say Hello":
        hello()

window.close()

要实时更新GUI,可以调用update(value, append=True)window.refresh,不要使用print语句,或者

以下代码显示了立即打印到 sg.multiline 的方法。为了避免停止 GUI 长时间打印,这里需要多线程。它不适用于事件循环期间的实时打印,因为循环正在处理您的打印语句,然后在完成后返回 window.read。

比较复杂,不知道有没有bug

import sys
from time import sleep
from datetime import datetime
import threading
import PySimpleGUI as sg

def print_task():
    global printing
    while printing:
        print(datetime.now().strftime("%H-%M-%S"), datetime.now().strftime("%H-%M-%S"))
        sleep(0.5)

class Unbuffered(object):
    def __init__(self, window):
        self.window = window
    def write(self, data):
        self.window.write_event_value("OUT", data)
    def writelines(self, datas):
        self.window.write_event_value("OUT", ''.join(datas))

frame_layout = [[sg.Multiline("", size=(80, 20), autoscroll=True, key='-OUTPUT-')]]

layout = [
    [sg.Frame("Output console", frame_layout)],
    [sg.Push(), sg.Button("Print"), sg.Button('Stop')],
]
window = sg.Window("Title", layout, finalize=True)
old_stdout, old_stderr = sys.stdout, sys.stderr
sys.stdout = Unbuffered(window)
sys.stderr = Unbuffered(window)
printing = False

while True:
    event, values = window.read()
    if event == sg.WINDOW_CLOSED:
        break
    elif event == 'Print':
        if not printing:
            printing = True
            threading.Thread(target=print_task, daemon=True).start()
    elif event == 'Stop':
            printing = False
    elif event == "OUT":
        window['-OUTPUT-'].update(values["OUT"], append=True)

printing = False
sys.stdout, sys.stderr = old_stdout, old_stderr
window.close()