Home > database >  display the CMD console in a window in GUI - PySimpleGUI
display the CMD console in a window in GUI - PySimpleGUI

Time:02-17

I'm creating a GUI using PySimpleGUI and want to have a frame that displays the output prints of all the functions in the program (as in the cmd console). I tried using (relevant code lines):

def hello():
    print('hello')

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

I can see the print in the console but not in the Frame in the GUI. How can i do that?

CodePudding user response:

To show the output like in CMD console, you should use the sg.Multiline, not the sg.Text which is just a label.

To redirect the output of stdout and stderr, set options reroute_stdout=True and reroute_stderr=True, also set option autoscroll=True to automatically scroll as more data added to the end of element.

Demo Code - GUI will update only back to 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()

To update GUI in realtime, you can call update(value, append=True) and window.refresh, not to use the print statement, or

Following code show the way to print to sg.multiline immediately. To avoid stop GUI working for long printing, mutlithread required here. It will not work for real time printing during event loop because loop is working on your printing statement, then back to window.read after it done.

It is much complex, not sure if any 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()
  • Related