I wrote a python 3.4.2 programme to get a user input from python IDLE, perform some processing on the input and display a few statements in the python IDLE using print().
Now I am in the process of converting this to use a GUI using tkinter. This is the simple tkinter code I wrote for the GUI.
from tkinter import *
root=Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe=Frame(root)
mainframe.grid(column=0, row=0)
inputval=StringVar()
inputentry=Entry(mainframe,textvariable=inputval).grid(column=1,row=1)
executebutton=Button(mainframe,text="Run",command=check_expression).grid(column=1,row=5)
outputtext=Text(mainframe).grid(column=1,row=5)
root.mainloop()
So far I was able to get the user input through the Entry widget named inputentry in the GUI and send it to a variable in the original code using inputval.get(). Then it performs the processing on the input and shows the outputs of print() statement in the python IDLE.
My question is how can I modify the programme to send all those print() statements to the Text widget named outputtext and display them in the GUI?
I would be glad if you could show me how to do this without using classes as I am a beginner in python
3 easy steps:
1) Get the content of your variable and put it to a variable that I'm gonna name varContent;
2) Clear your text widget, that is, if the name of your text widget is text, then run text.delete(0, END);
3) Insert the string you've got in your variable varContent into your text text widget, that is, do text.insert(END, varContent).
I would do my code like this:
from tkinter import *
def check_expression():
#Your code that checks the expression
varContent = inputentry.get() # get what's written in the inputentry entry widget
outputtext.delete('0', 'end-1c') # clear the outputtext text widget
outputtext.insert(varContent)
root = Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe = Frame(root)
mainframe.grid(column=0, row=0)
inputentry = Entry(mainframe)
inputentry.grid(column=1, row=1)
executebutton = Button(mainframe, text="Run", command=check_expression)
executebutton.grid(column=1, row=5)
outputtext = Text(mainframe)
outputtext.grid(column=1, row=5)
root.mainloop()
For Python 3.x
After creating the entry box with inputentry=Entry(mainframe).grid() you can get the typed entries with inputentry.get().
Do the following to put the typed entry in a variable and to print it in the text widget named outputtext:
entryvar=inputentry.get() # the variable entryvar contains the text widget content
outputtext.delete(1.0,tk.END) # clear the outputtext text widget. 1.0 and tk.END are neccessary. tk implies the tkinter module. If you just want to add text dont incude that line
outputtext.insert(tk.END,entryvar) # insert the entry widget contents in the text widget. tk.END is necessary.
If you're using Python 3.4+ to run the program too, you can use the contextlib.redirect_stdout to capture the print output for a duration of a few statements into a file, or even a string:
import io
from contextlib import redirect_stdout
...
file = io.StringIO()
with redirect_stdout(file):
# here be all the commands whose print output
# we want to capture.
output = file.getvalue()
# output is a `str` whose contents is everything that was
# printed within the above with block.
Otherwise a better though a bit more arduous way is to make a StringIO file and print to it, so you'd have
buffer = io.StringIO()
print("something", file=buffer)
print("something more", file=buffer)
output = buffer.getvalue()
text.insert(END, output)
Related
I started literally a couple of days ago, and I need help :(
I want to create a program to translate a phrase to something else
Ex:
Program
000000000000000000000000000000000000000000
"Phrase to translate"
(Here the person writes the sentence)
A button to activate the command
(And here the translated phrase appears)
000000000000000000000000000000000000000000
Or something like that
I already have the code to change the words, and I am creating the interface, and I have already learned to create windows but I still don't know how to paste my translation :(
This is what I have
frase=input("Escribe la frase: ")
entrada="abcdefghilmnopqrstuvxyz"
salida="mnopqrstuvxyzabcdefghil"
letras=frase.maketrans(entrada,salida)
print(frase.translate(letras))
import tkinter as tk
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
frase=tk.Entry(ventana)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white")
root.pack(padx=20,pady=10)
How can I "combine" these two codes (?
What you need to do is create a tk widget called label:
label = tk.Label(ventana, width=20)
label.pack()
Then you can simply make a function called translate and configure the text of the label however you want
def translate(phrase):
label.config(text=phrase)
lastly you should bind the function translate to the button so that when you press it the magic happens:)
Like this:
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white", command=lambda: translate(phrase=frase.get()))
This is some ready to try code based on your question
import tkinter as tk
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
frase=tk.Entry(ventana)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
label = tk.Label(ventana, width=20)
label.pack()
dic = {'Hello':'Bonjour'}
def translate(phrase):
if phrase in dic.keys():
text = dic[phrase]
else:
text='Cannot translate text'
label.config(text=text)
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white", command=lambda: translate(phrase=frase.get()))
root.pack(padx=20,pady=10)
ventana.mainloop()
For the translation part the best you can do is create a dictionary. This way when someone enters a specific word in your EntryBox the program will be able to translate it:
You can do so like this:
dic = {'Good Morning':'Bonjour', 'Yes':'Oui'}
def translate(phrase):
if phrase in dic.keys():
text = dic[phrase]
else:
text='Cannot translate text'
label.config(text=text)
Last but not least, it's usually good to add a mainloop() call in the end of your program so as for the events happening in your app to be handled correctly. In your case you should add ventana.mainloop()
Please try this piece of code.
import tkinter as tk
def translate():
#==== Forget the position of the widgets in the window
for widget in ventana.winfo_children():
widget.pack_forget()
#=== Again place the entry box and the button
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root.pack(padx=20,pady=10)
#==== Provide the text entered in the entry field
entrada="abcdefghilmnopqrstuvxyz"
salida="mnopqrstuvxyzabcdefghil"
letras=org_phrase.get().maketrans(entrada,salida)
#===print the translation (optional)
print(org_phrase.get().translate(letras))
#=== set it as label to display it
tk.Label(ventana,bg="white",text=org_phrase.get().translate(letras)).pack()
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
#=== Using stringvar to get the value
org_phrase=tk.StringVar()
#trans_phrase=tk.StringVar()
frase=tk.Entry(ventana,textvariable=org_phrase)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root =tk.Button(ventana,text="Traducir:",bg="black",fg="white",command=translate)
root.pack(padx=20,pady=10)
root.mainloop()
In python, I am attempting the change the width of the tkinter messagebox window so that text can fit on one line.
import tkinter as tk
from tkinter import messagebox
root = tk.Tk()
messagebox.showinfo("info","this information goes beyond the width of the messagebox")
root.mainloop()
It's not possible to adjust the size of messagebox.
When to use the Message Widget
The widget can be used to display short text messages, using a single font. You can often use a plain Label instead. If you need to display text in multiple fonts, use a Text widget. -effbot
Also see:
Can I adjust the size of message box created by tkMessagebox?
#CharleyPathak is correct. You either need to put a newline in the middle of the text, because message boxes can display multiple lines, or create a custom dialog box.
Heres another method that gets the effect youre looking for but doesnt use messagebox. it looks a lot longer but it just offers much more in terms of customization.
def popupmsg():
popup = tk.Tk()
def leavemini():
popup.destroy()
popup.wm_title("Coming Soon")
popup.wm_attributes('-topmost', True) # keeps popup above everything until closed.
popup.wm_attributes("-fullscreen", True) # I chose to make mine fullscreen with transparent effects.
popup.configure(background='#4a4a4a') # this is outter background colour
popup.wm_attributes("-alpha", 0.95) # level of transparency
popup.config(bd=2, relief=FLAT) # tk style
# this next label (tk.button) is the text field holding your message. i put it in a tk.button so the sizing matched the "close" button
# also want to note that my button is very big due to it being used on a touch screen application.
label = tk.Button(popup, text="""PUT MESSAGE HERE""", background="#3e3e3e", font=headerfont,
width=30, height=11, relief=FLAT, state=DISABLED, disabledforeground="#3dcc8e")
label.pack(pady=18)
close_button = tk.Button(popup, text="Close", font=headerfont, command=leavemini, width=30, height=6,
background="#4a4a4a", relief=GROOVE, activebackground="#323232", foreground="#3dcc8e",
activeforeground="#0f8954")
close_button.pack()
I managed to have a proper size for my
"tkMessageBox.showinfo(title="Help", message = str(readme))" this way:
I wanted to show a help file (readme.txt).
def helpfile(filetype):
if filetype==1:
with open("readme.txt") as f:
readme = f.read()
tkMessageBox.showinfo(title="Help", message = str(readme))
I opened the file readme.txt and EDITED IT so that the length of all lines did not exeed about 65 chars. That worked well for me. I think it is important NOT TO HAVE LONG LINES which include CR/LF in between. So format the txt file properly.
i have a problem and can't get my head around it. How to create a child window on pressing a button using tkinter in python were I can entry values like for example:
import tkinter
root = Tk()
Button(root, text='Bring up Message', command=Window).pack()
root.mainloop()
def messageWindow():
win = Toplevel()
-------->calculate------
Label(win, text=message).pack()
Button(win, text='OK', command=win.destroy).pack()
and on the message window i would like to have two entry fields were I can enter a and b and afterwards it should calc a+b and give me the result.
Thank you.
First, you should use from tkinter import * since there isn't a tkinter. preceding the module's classes used in your script.
Also, is your "Bring up Message" button supposed to call the messageWindow() function? Right now it's calling an undefined function Window. If so, you should change the Button's command and move your messageWindow() function above the line where you created the button or else it will call the function before it is defined and generate an error.
The syntax of an Entry widget in Tkinter goes as follows:
entry = Entry(root, *options)
entry.pack()
You need to pack() the entry widget after you define it. You won't be able to retrieve the input inside it if you pack() it on the same line as you define it as it will become a NoneType object.
You will need at least two Entry widgets, one to enter input a and one to enter input b.
You can also add a third Entry to print the result of the sum of a and b to, though you can use a label or just print it to the console.
entry_a = Entry(win)
entry_a.pack()
entry_b = Entry(win)
entry_b.pack()
# Optional answer entry
entry_ans = Entry(win)
entry_ans.pack()
You should then create a function (still within the messageWindow() function) that will retrieve the input from the two entries and add them, as well as another Button to call that function. I implemented some additional error-checking in the form of a try-except for when the entries are blank or contain something other than integers:
def add():
try:
a = int(entry_a.get())
b = int(entry_b.get())
ab_sum = a + b
# Optional printing to answer entry
entry_ans.delete(0, 'end')
entry_ans.insert(0, ab_sum)
except:
pass
Button(win, text="Add", command=add).pack()
"How to create entry inputs in a toplevel window"
import tkinter as tk
...
toplevel = tk.Toplevel(...)
tk.Entry(toplevel)
"How to create a child window on pressing a button..."
import tkinter as tk
...
def create_child_window(widget):
tk.Toplevel(widget)
...
root = tk.Tk()
tk.Button(root, command=lambda w = root: create_child_window(w))
I'd like to distribute my program around the office so other people can use it when I'm not in
my code:
from tkinter import *
import os
top = Tk()
top.wm_title("testest")
top.minsize(width=300, height=150)
top.maxsize(width=300, height=150)
def runscript():
os.system('python test.py')
B = Tk.Button(top, text = 'Run test', command = runscript)
B.config(width=15, height=1)
B.pack()
top.mainloop()
Is there any way I can have my print functions in the .py file print out in a GUI text box instead of the command line?
Here's a crude demo that shows how to print text strings to a Label. Note that long strings are not wrapped. If you need that, you'll have to wrap the strings yourself by inserting \n newline characters, or use the wraplength option, as mentioned in the Label widget docs. Alternatively, you could use a Text widget instead of a Label to display the text.
My test function simulates the action of the code in your "test.py" script.
import tkinter as tk
from time import sleep
# A dummy `test` function
def test():
# Delay in seconds
delay = 2.0
sleep(delay)
print_to_gui('Files currently transferring')
sleep(delay)
print_to_gui('Currently merging all pdfs')
sleep(delay)
print_to_gui('PDFs have been merged')
sleep(delay)
print_to_gui('Finished!\nYou can click the "Run test"\n'
'button to run the test again.')
# Display a string in `out_label`
def print_to_gui(text_string):
out_label.config(text=text_string)
# Force the GUI to update
top.update()
# Build the GUI
top = tk.Tk()
top.wm_title("testest")
top.minsize(width=300, height=150)
top.maxsize(width=300, height=150)
b = tk.Button(top, text='Run test', command=test)
b.config(width=15, height=1)
b.pack()
# A Label to display output from the `test` function
out_label = tk.Label(text='Click button to start')
out_label.pack()
top.mainloop()
Note that we normally do not call time.sleep in a GUI program because it causes the whole program to freeze while the sleep is occurring. I've used it here to simulate the blocking delay that will occur when your real code is performing its processing.
The usual way to do delays in a Tkinter program that doesn't block normal GUI processing is to use the .after method.
You will notice that I replaced your from tkinter import * with import tkinter as tk. This means we need to type eg tk.Labelinstead of Label, but that makes the code easier to read, since we now know where all the different names come from. It also means we aren't flooding our namespace with all the names that tkinter defines. import tkinter as tk just adds 1 name to the namespace, from tkinter import * adds 136 names in the current version. Please see Why is “import *” bad? for further info on this important topic.
Here's a slightly fancier example that appends new text to the current Label text, with word wrapping. It also has a function clear_label to remove all the text from the Label. Rather than storing the text directly in the Label it uses a StringVar. This makes it easier to access the old text so that we can append to it.
import tkinter as tk
from time import sleep
# A Dummy `test` function
def test():
# Delay in seconds
delay = 1.0
clear_label()
print_to_label('Files currently transferring')
sleep(delay)
print_to_label('Currently merging all pdfs')
sleep(delay)
print_to_label('PDFs have been merged')
sleep(delay)
print_to_label('\nFinished!\nYou can click the "Run test" '
'button to run the test again. '
'This is a very long string to show off word wrapping.'
)
# Append `text_string` to `label_text`, which is displayed in `out_label`
def print_to_label(text_string):
label_text.set(label_text.get() + '\n' + text_string)
# Force the GUI to update
top.update()
def clear_label():
label_text.set('')
top.update()
# Build the GUI
top = tk.Tk()
top.wm_title("testest")
top.minsize(width=300, height=150)
top.maxsize(width=300, height=350)
b = tk.Button(top, text='Run test', command=test)
b.config(width=15, height=1)
b.pack()
# A Label to display output from the `test` function
label_text = tk.StringVar()
out_label = tk.Label(textvariable=label_text, wraplength=250)
label_text.set('Click button to start')
out_label.pack()
top.mainloop()
I am new to Tkinter, I have the following code:
from Tkinter import *
root = Tk()
root.title("Email Sender")
Label(root, text="To").grid(row=0)
text = StringVar()
toText = Entry(root, textvariable=text)
s= text.get()
root.mainloop()
My goal is to create a label "To" and an entry, I am trying to capture whatever typed from keyboard in the entry. However, with the above code, I got empty when I print s.
So how could I capture the text typed into the entry?
Thanks.
You are capturing the text typed into the Entry—but you're only doing s = text.get() once, before the mainloop has even started, at which point the text typed into the Entry is whatever the initial value of the Entry was, which is the empty string.
What you need to do is add an event handler that runs at the appropriate time—maybe on the root's close event, or each time the Entry's text is edited, or whatever seems right to you—and does the s = text.get(). Then, you'll have whatever was in the Entry at the time that event was fired.