Display the Output of the Program on Gui with Tkinter

Display the output of the program on GUI with tkinter?

I took the time to debug and modify the errorwindow.py module in my answer to another question so it will work in both Python 2 and 3—the code in the linked answer was written for Python 2.x. Note I only did the minimum necessary to get it functioning under the two versions. The modified version of the script has been named errorwindow3k.py (despite that fact it also works in Python 2).

The majority of the issues were simply due to module renaming, however there was a harder one to figure-out that turned-out was due to the switch to Unicode strings being the default string-type in version 3—apparently (on Windows anyway), pipes between processes are byte-streams, not Unicode characters. Fortunately the "fix" of decoding and then encoding the data on the other side also doesn't hurt in Python 2 which made correcting the problem fairly easy.

This nice thing is that using it is very easy. Just import it and from that point on any output sent to either sys.stderr or sys.stdout will cause tkinter-based output windows to appear as needed to display the information. In your sample code just insert import errorwindow3k somewhere before the print("Hello world").

File errorwindow3k.py:

# Code derived from Bryan Olson's source posted in this related Usenet discussion:
# https://groups.google.com/d/msg/comp.lang.python/HWPhLhXKUos/TpFeWxEE9nsJ
# https://groups.google.com/d/msg/comp.lang.python/HWPhLhXKUos/eEHYAl4dH9YJ
#
# See the comments and doc string below.
#
# Here's a module to show stderr output from console-less Python
# apps, and stay out of the way otherwise. I plan to make a ASPN
# recipe of it, but I thought I'd run it by this group first.
#
# To use it, import the module. That's it. Upon import it will
# assign sys.stderr.
#
# In the normal case, your code is perfect so nothing ever gets
# written to stderr, and the module won't do much of anything.
# Upon the first write to stderr, if any, the module will launch a
# new process, and that process will show the stderr output in a
# window. The window will live until dismissed; I hate, hate, hate
# those vanishing-consoles-with-critical-information.
#
# The code shows some arguably-cool tricks. To fit everthing in
# one file, the module runs the Python interpreter on itself; it
# uses the "if __name__ == '__main__'" idiom to behave radically
# differently upon import versus direct execution. It uses tkinter
# for the window, but that's in a new process; it does not import
# tkinter into your application.
#
# To try it out, save it to a file -- I call it "errorwindow.py" -
# - and import it into some subsequently-incorrect code. For
# example:
#
# import errorwindow
#
# a = 3 + 1 + nonesuchdefined
#
# should cause a window to appear, showing the traceback of a
# Python NameError.
#
# --
# --Bryan
# ----------------------------------------------------------------
#
# martineau - Modified to use subprocess.Popen instead of the os.popen
# which has been deprecated since Py 2.6. Changed so it
# redirects both stdout and stderr. Added numerous
# comments, and also inserted double quotes around paths
# in case they have embedded space characters in them, as
# they did on my Windows system.
#
# Recently updated it to work in both Python 2 and Python 3.

"""
Import this module into graphical Python apps to provide a
sys.stderr. No functions to call, just import it. It uses
only facilities in the Python standard distribution.

If nothing is ever written to stderr, then the module just
sits there and stays out of your face. Upon write to stderr,
it launches a new process, piping it error stream. The new
process throws up a window showing the error messages.
"""
import subprocess
import sys
try:
import thread
except ModuleNotFoundError: # Python 3
import _thread as thread
import os

EXC_INFO_FILENAME = 'exc_info.txt'

if __name__ == '__main__': # When spawned as separate process.
# create window in which to display output
# then copy stdin to the window until EOF
# will happen when output is sent to each OutputPipe created
try:
from Tkinter import BOTH, END, Frame, Text, TOP, YES
import tkFont
import Queue
except ModuleNotFoundError: # Python 3
from tkinter import BOTH, END, Frame, Text, TOP, YES
import tkinter.font as tkFont
import queue as Queue

Q_EMPTY = Queue.Empty # An exception class.
queue = Queue.Queue(1000) # FIFO

def read_stdin(app, bufsize=4096):
fd = sys.stdin.fileno() # File descriptor for os.read() calls.
read = os.read
put = queue.put
while True:
put(read(fd, bufsize))

class Application(Frame):
def __init__(self, master=None, font_size=8, text_color='#0000AA', rows=25, cols=100):
Frame.__init__(self, master)
# Create title based on the arguments passed to the spawned script:
# argv[0]: name of this script (ignored)
# argv[1]: name of script that imported this module
# argv[2]: name of redirected stream (optional)
if len(sys.argv) < 2:
title = "Output stream from unknown source"
elif len(sys.argv) < 3:
title = "Output stream from %s" % (sys.argv[1],)
else: # Assume it's a least 3.
title = "Output stream '%s' from %s" % (sys.argv[2], 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) # Force frame to be configured size.

self.logwidget = Text(self, font=font)
self.logwidget.pack(side=TOP, fill=BOTH, expand=YES)
# Disallow key entry, but allow text copying with <Control-c>
self.logwidget.bind('<Key>', lambda x: 'break')
self.logwidget.bind('<Control-c>', lambda x: None)
self.logwidget.configure(foreground=text_color)
self.logwidget.insert(END, '==== Start of Output Stream ====\n\n')
self.logwidget.see(END)
self.after(200, self.start_thread) # Start queue polling 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().decode() # Must decode for Python 3.
if not data:
data = '[EOF]'
go = False
log_insert(END, data)
log_see(END)
except Q_EMPTY:
self.after(200, self.check_q)
go = False

app = Application()
app.mainloop()

else: # when module is first imported
import traceback

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

def flush(self): # no-op.
pass

def __getattr__(self, attr):
if attr == 'pipe': # Attribute doesn't exist, so create it.
# Launch this module as a separate process to display any output
# it receives.
# Note: It's important to put double quotes around everything in
# case any have embedded space characters.
command = '"%s" "%s" "%s" "%s"' % (sys.executable, # executable
__file__, # argv[0]
os.path.basename(sys.argv[0]), # argv[1]
self.name) # argv[2]
#
# Typical command and arg values on receiving end:
# C:\Python3\python[w].exe # executable
# C:\vols\Files\PythonLib\Stack Overflow\errorwindow3k.py # argv[0]
# errorwindow3k_test.py # argv[1]
# stderr # argv[2]

# Execute this script directly as __main__ with a stdin PIPE for sending
# output to it.
try:
# Had to also make stdout and stderr PIPEs too, to work with pythonw.exe
self.pipe = subprocess.Popen(command, bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stdin
except Exception:
# Output exception info to a file since this module isn't working.
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_FILENAME, 'wt') as info:
info.write('fatal error occurred spawning output process')
info.write('exeception info:' + msg)
traceback.print_exc(file=info)

sys.exit('fatal error occurred')

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

def write(self, data):
with self.lock:
data = data.encode() # Must encode for Python 3.
self.pipe.write(data) # First reference to pipe attr will cause an
# OutputPipe process for the stream to be created.

# Clean-up any left-over debugging file.
try:
os.remove(EXC_INFO_FILENAME) # Delete previous file, if any.
except Exception:
pass

# Redirect standard output streams in the process that imported this module.
sys.stderr = OutputPipe('stderr')
sys.stdout = OutputPipe('stdout')

If you have any questions about how it works, feel free to ask in the comments.

How to display function output to Tkinter GUI?

Improved Your code a bit:

import tkinter as tk
import random

window = tk.Tk()
window.title(" Magical Name Generator ")

window.geometry("400x400")

# Functions.
def name_gen():
"""
This function randomly concatenates items from
two lists and combines them in one name.
"""
first = ("ara", "isil", "ar", "beo", "boro", "dene", "bele", "eo",
"teo", "ea", "el", "ele", "ele", "fara", "fea", "dea",
"bere", "feo", "fan", "tau")
second = ("gorn", "dur", "wen", "orn", "mir", "thor", "den", "dred",
"ndil", "dil", "wing", "rond", "mer", "wyn", "nor", "gal",
"zar", "nar", "mar", "dorn", "ron")
first_part = random.choice(first)
second_part = random.choice(second)
name = (first_part + second_part)
print(name.title())
return name.title()

def name_plot():
temp_lst = []
for _ in range(10):
temp_lst.append(name_gen())
return '\n'.join(temp_lst)

def display_name():
show_up = name_plot()
text = tk.Text(master=window, height=10, width=30)
text.grid(column=0, row=5)
text.insert(tk.END, show_up)

# Labels
label_head = tk.Label(text=" Hello, Wanderer! \n Choose your name wisely. ", font=("The New Roman", 25))
label_head.grid()

label_enter = tk.Label(text=" Pick the one that suits you best. ")
label_enter.grid(column=0, row=1)

label_output = tk.Label(text=display_name())
label_output.grid()

# Button
button_submit = tk.Button(text="Generate", bg="green", command=display_name)
button_submit.grid(column=0, row=11)

window.mainloop()

Display python (constantly changing) 'print output' to tkinter GUI textbox (flush?)

I made an example displaying Your cpi in cmdline, tkinter and pyqt5.

I simplified Your cpi counter and made it in class. Sorry to change Your code completely, but like that it's more suitable to work with multiple output interfaces. In principle, You can use Your code, but it must not be blocking.

Let's start with file click_counter.py, it will hold ClickCounter class, which is our back-end, counting clicks in user defined interval (default is 1 second).

from threading import Thread, Event
from typing import Callable

from pynput.mouse import Listener

class ClickCounter(Thread):
"""Click counter, counting clicks / interval"""
click_count = 0
stopped = Event()

def __init__(self, callback: Callable, interval: float = 1.0) -> None:
super().__init__()
self.interval = interval
self.callback = callback
self.listener = Listener(on_click=self.click_counter)

def run(self) -> None:
"""Start mouse click listener and timer"""
self.listener.start()

while not self.stopped.wait(self.interval):
# Call callback with click counter value, after interval expires
self.callback(self.click_count)
# Reset counter
self.click_count = 0

def click_counter(self, x: float, y: float, button: int, pressed: bool) -> None:
"""Count clicks"""
if pressed:
# Count when mouse button is pressed
self.click_count += 1

def cancel(self) -> None:
"""Cancel counter timer"""
# Stop timer
self.stopped.set()
# Stop listener
self.listener.stop()

Then we can define different output interfaces.

Let's start with cps_cmdline.py, which displays cps in command line:

import signal
from time import sleep

from click_counter import ClickCounter

def print_counter(count):
print("\r", end="")
print(count, 'cps', end="")

click_counter = ClickCounter(print_counter)
click_counter.start()

stopped = False

def exit_app(*args):
"""Close counter and app"""
global stopped, click_counter
click_counter.cancel()
stopped = True

# Register kill signals
signal.signal(signal.SIGINT, exit_app)
signal.signal(signal.SIGTERM, exit_app)

while not stopped:
# Just run until stopped
sleep(0.1)

To display cps in tkinter, use code in file cps_tkinter.py:

import tkinter as tk

from cps.click_counter import ClickCounter

class Window(tk.Frame):

def __init__(self, master=None):
"""Create label and StringVar holding its text"""
super().__init__(master)
self.master = master
self.pack(fill=tk.BOTH, expand=1)
self.cps_text = tk.StringVar(value="0 cps")
self.cps_label = tk.Label(self, textvariable=self.cps_text)
self.cps_label.place(relx=0.5, rely=0.5, anchor='center')

def print_counter(self, count):
"""Thread safe variable set"""
self.after(0, self.cps_text.set, f"{count} cps")

if __name__ == "__main__":
root = tk.Tk()
app = Window(root)
root.wm_title("CPS counter")
root.geometry("100x100")

# Create and start counter
click_counter = ClickCounter(app.print_counter)
click_counter.start()

# Start tkinter app
root.mainloop()
# tkinter app is over, cancel click_counter
click_counter.cancel()

And last but not least cps_qt5.py:

import sys

from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout

from cps.click_counter import ClickCounter

class Window(QWidget):
sig_print_counter = pyqtSignal(int)

def __init__(self, parent=None):
"""Create label and StringVar holding its text"""
super().__init__(parent)
self.cps_label = QLabel()
self.cps_label.setText("0 cps")
self.resize(100, 100)
layout = QHBoxLayout()
layout.setAlignment(Qt.AlignHCenter)
layout.addWidget(self.cps_label)
self.setLayout(layout)
self.sig_print_counter.connect(self.print_counter)

@pyqtSlot(int)
def print_counter(self, count):
"""Thread safe label text set"""
self.cps_label.setText(f"{count} cps")

if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()

# Create and start counter
click_counter = ClickCounter(window.sig_print_counter.emit)
click_counter.start()

app.exec()
# Qt app is over, cancel click_counter
click_counter.cancel()

Show output of Python script in Tkinter GUI

print() only sends text on screen. It never returns displayed text.

To assign to variable use it without print() - ie.

diffvalue = "Image similarity %ge of_{}_&_{}_is {}".format(filename, templateFilename, score * 100)

And now you can display text in Label or Text or Listbox


To append text to Label you have to get old text from Label, concatenate new text to old text, and put all again to Label - ie

new_text = 'diff_per {}_&_{} saved'.format(filename, templateFilename)
Difference_per_label["text"] = Difference_per_label["text"] + "\n" + new_text

or shorter wiht +=

Difference_per_label["text"] += "\n" + new_text

Because tkinter (and other GUIs) doesn't update widget in window when you change text in label but when it ends function executed by Button and it returns to mainloop so you may have to use root.update() after changing text in Label to force mainloop() to redraw windgets in window.


To throw exception you need raise(), not try/except which is used to catch exception.

And to test if there is no file you would have to get all data from os.listdir() as list, filter list with endswith() and check if list is empty.

import os

sourceDirectory = '.'

all_files = os.listdir(sourceDirectory)
all_files = [os.fsdecode(file) for file in all_files]
#all_files = map(os.fsdecode, all_files)
all_files = [file for file in all_files if file.lower().endswith((".jpg",".png"))]

#if len(all_files) == 0:
if not all_files:
raise(Exception("No Files"))

How to make my output appear in tkinter GUI instead of shell?

There are several issues in your code. The problem you stated is due to calling print(...) in text=print(...). You don't need to call print(...), just assign the argument of print(...) to text is enough.

Also you should not recreate Text widgets every time you click Yes button. You should create Label widgets to display the random result once and then change their text in print_start_life() function.

Below is a modified version of your code:

import random
from tkinter import *

# Attributes
age = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20",
"21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58",
"59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77",
"78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96",
"97", "98", "99", "100", ]
country = ["United States", "Brazil", "Mexico", "China", "Japan", "Canada", "France", "Germany"]
male_name = ["Joe", "Eden", "Diego", "Anthony", "Jarod", "Kique", "Austin", "Hunter"]
female_name = ["Haley", "Ariana", "Sarah", "Jackie", "Serena"]
gender_male = "Male"
gender_female = "Female"

# Random Generation
def print_start_life(event=None):
selected_age.config(text=random.choice(age))
selected_country.config(text=random.choice(country))
name = random.choice(male_name+female_name)
selected_name.config(text=name)
gender.config(text=gender_male if name in male_name else gender_female)

# GUI
window = Tk()
window.title("Random Life")
window.geometry('800x500')
lbl = Label(window, text="Do you want to play Random Life?", font=("Arial Bold", 25))
lbl.grid(column=0, row=0)

btn = Button(window, text="Yes", command=print_start_life)
#btn.bind("<Button-1>", print_start_life)
btn.grid(column=1, row=0)

frm = Frame(window)
font1 = ("Arial", 16)
font2 = ("Arial Bold", 16)
Label(frm, text='Age:', font=font1).grid(row=0, column=0, sticky=E)
selected_age = Label(frm, font=font2)
selected_age.grid(row=0, column=1, sticky=W)

Label(frm, text='Country:', font=font1).grid(row=1, column=0, sticky=E)
selected_country = Label(frm, font=font2)
selected_country.grid(row=1, column=1, sticky=W)

Label(frm, text='Name:', font=font1).grid(row=2, column=0, sticky=E)
selected_name = Label(frm, font=font2)
selected_name.grid(row=2, column=1, sticky=W)

Label(frm, text="Gender:", font=font1).grid(row=3, column=0, sticky=E)
gender = Label(frm, font=font2)
gender.grid(row=3, column=1, sticky=W)

frm.grid(row=1, sticky=W)

window.mainloop()

How to display input and output in same GUI for tkinter in Python

Well I tried to understand what you really want, but couldnt get it, so I put together what I feel that you might want, with an example:

from tkinter import *

class Custombox:
def __init__(self, title, text):
self.title = title
self.text = text

def store():
self.new = self.entry.get() #storing data from entry box onto variable
if self.new == 'Hello World': #checking
a.change('ACCEPTED') #changing text
else:
a.change('REJECTED') #else, changing text

self.win = Toplevel()
self.win.title(self.title)
# self.win.geometry('400x150')
self.win.wm_attributes('-topmost', True)

self.label = Label(self.win, text=self.text)
self.label.grid(row=0, column=0, pady=(20, 10),columnspan=3,sticky='w',padx=10)

self.l = Label(self.win)

self.entry = Entry(self.win, width=50)
self.entry.grid(row=1, column=1,columnspan=2,padx=10)

self.b1 = Button(self.win, text='Ok', width=10,command=store)
self.b1.grid(row=3, column=1,pady=10)

self.b2 = Button(self.win, text='Cancel', width=10,command=self.win.destroy)
self.b2.grid(row=3, column=2,pady=10)

def __str__(self):
return str(self.new)

def change(self,ran_text):
self.l.config(text=ran_text,font=(0,12))
self.l.grid(row=2,column=1,columnspan=3,sticky='nsew',pady=5)

root = Tk()
root.withdraw()

a = Custombox('Custom box', 'Enter a string within the alphabet {a,b}*. Suffix must be bb.')

root.mainloop()

Over here im creating a window using basic tkinter properties and placements and all you have to understand is that store() inside that class is similar to your q3() as I couldnt understand what was going on there, I just made my own function. So you will have to replace store() with what works for you, but do not change the self.new = self.entry.get(). Yes this might seem a bit shady, but it was the quickest i could do, because im a beginner as well.

Anyways here, a has the value of whatever you type into the entry widget, BUT while using a, make sure to use str(a) or you wont get correct results as type(a) returns <class '__main__.Custombox'>. Do let me know if you face any difficulty in the implementation of this class. I know there are mistakes here, feel free to edit those mistakes out or let me know.

How do I make my python tkinter output to show in GUI instead of python shell?

To print text into a tkinter GUI, you need a separate label widget.

Check the code below. I have added the widget Return_Label, which you can change the config and position of to however you like. I'm pretty sure this should do what you want.

#These variables are made global so both functions can access them
var = None
Return_Label = None

def serial_port():
global var, Return_Label

selection = var.get()
text_dict = {
1: "Africa",
2: "North America",
3: "Asia",
4: "Australia"}
text_to_print = text_dict[selection]
Return_Label.config(text = text_to_print)

def main():
global var, Return_Label

root = tk.Tk()
root.title("Continent")
root.geometry("500x300")
var = tk.IntVar()
var.set(1)

Lang_1 = tk.Radiobutton(root, text = "Nigeria", variable = var, value = 1, width = 20)
Lang_2 = tk.Radiobutton(root, text = "Canada", variable = var, value = 2, width = 20)
Lang_3 = tk.Radiobutton(root, text = "Japan", variable = var, value = 3, width = 20)
Lang_4 = tk.Radiobutton(root, text = "Australia", variable = var, value = 4, width = 20)

Enter_Button = tk.Button(root, text = "ENTER", command = serial_port, relief = "ridge", bg = "Cyan", width = 20)

Return_Label = tk.Label(root)

Lang_1.grid(row = 1, column = 5)
Lang_2.grid(row = 2, column = 5)
Lang_3.grid(row = 3, column = 5)
Lang_4.grid(row = 4, column = 5)
Enter_Button.grid(row = 7, column = 3)
Return_Label.grid(row = 6, column = 3) #change this to wherever you want it printed
root.mainloop()

if (__name__ == "__main__"):
main()

How can I displaymy console output in TKinter?

You can do the following:

import sys
from tkinter import Tk, Button, Frame
from tkinter.scrolledtext import ScrolledText

class PrintLogger(object): # create file like object

def __init__(self, textbox): # pass reference to text widget
self.textbox = textbox # keep ref

def write(self, text):
self.textbox.configure(state="normal") # make field editable
self.textbox.insert("end", text) # write text to textbox
self.textbox.see("end") # scroll to end
self.textbox.configure(state="disabled") # make field readonly

def flush(self): # needed for file like object
pass

class MainGUI(Tk):

def __init__(self):
Tk.__init__(self)
self.root = Frame(self)
self.root.pack()
self.redirect_button = Button(self.root, text="Redirect console to widget", command=self.redirect_logging)
self.redirect_button.pack()
self.redirect_button = Button(self.root, text="Redirect console reset", command=self.reset_logging)
self.redirect_button.pack()
self.test_button = Button(self.root, text="Test Print", command=self.test_print)
self.test_button.pack()
self.log_widget = ScrolledText(self.root, height=4, width=120, font=("consolas", "8", "normal"))
self.log_widget.pack()

def reset_logging(self):
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

def test_print(self):
print("Am i working?")

def redirect_logging(self):
logger = PrintLogger(self.log_widget)
sys.stdout = logger
sys.stderr = logger

if __name__ == "__main__":
app = MainGUI()
app.mainloop()

Print output in GUI interface Tkinter Python

Using print only prints to the terminal or a fp. You can create a new Label to "print" to the GUI.

from Tkinter import *

def printSomething():
# if you want the button to disappear:
# button.destroy() or button.pack_forget()
label = Label(root, text= "Hey whatsup bro, i am doing something very interresting.")
#this creates a new label to the GUI
label.pack()

root = Tk()

button = Button(root, text="Print Me", command=printSomething)
button.pack()

root.mainloop()

AN EXAMPLE FOR YOUR COMMENT



Related Topics



Leave a reply



Submit