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()