Tkinter: How do I get the value after clicking the button? - python

I am very new to Tkinter and GUI in general, but I tried looking around for similar problems (and found some) and I still can't seem to get it to work. I want to save the stringpath "path_to_ifc_file" after clicking the button, so that I can use it in another script later on.
from tkinter import *
from tkinter import filedialog
def BrowseFiles():
path_to_ifc_file = filedialog.askopenfilename(initialdir="../models/", title="Get Ifc-File:",
filetypes=(("Ifc-Files", "*.ifc*"), ("All files", "*.*")))
if path_to_ifc_file == "":
label_file_explorer.configure(text="Get Ifc-File:")
else:
label_file_explorer.configure(text="Found Ifc-File: \n" + Path(path_to_ifc_file).stem + ".ifc")
return path_to_ifc_file
# WINDOW CONFIGURATION
window = Tk()
window.title('Test')
window.geometry("800x280")
# INITIALIZE WIDGETS
label_file_explorer = Label(window, text="Get Ifc-File:")
button_explore = Button(window, text="Browse", command=BrowseFiles)
# DISPLAY WIDGETS
label_file_explorer.grid(column=1, row=1)
button_explore.grid(column=2, row=1)
window.mainloop()
In my mind I just want something like
path_to_ifc_file=<returned value path_to_ifc_file from function BrowseFiles()>
I appreciate every help I can get! Thanks in advance :)

Related

Changing Tkinter label while app is still running

Could not find exact answer to my question in other posts. What I am looking for is the way to update my label while my other function is running. I tried to first change the label and then call the my_function(), but still label is not updating however my_function() is running and printing results in terminal. I am totally new to Tkinter and as far as I understood, while we do not hit window.mainloop() my label would not update. Is there any methods to update the label while other function is running?
import os
import tkinter as tk
from tkinter import END, Label, Scrollbar, Text, filedialog
def my_function(directory: str) -> None:
for item in os.scandir(directory):
if item.is_file:
# print(f'File name: {item.name}')
text_area.insert(END, f'File name: {item.name}\n')
def select_folder() -> None:
'''
Tkinter function for button,
user can select folder.
'''
path = filedialog.askdirectory()
status.config(text='Status: Work in progress, please wait!')
text_area.insert(END, 'Visited folders:\n')
my_function(path)
status.config(text='Status: Done!')
# Start the app window
window = tk.Tk()
window.title('PDF maker')
window.geometry('400x400')
# Status Label
status = Label(window, text='Status: Select the folder')
status.pack()
# Button for selecting folder
button = tk.Button(window, text='Select Folder', command=select_folder)
button.pack(side='bottom', pady=30)
# Horizontal and Vertical Scrollbars
v_s = Scrollbar(window)
v_s.pack(side='right', fill='y')
h_s = Scrollbar(window, orient='horizontal')
h_s.pack(side='bottom', fill='x')
# Text area for result output
text_area = Text(
window,
wrap='none',
font=('Times New Roman', 13),
yscrollcommand=v_s.set,
xscrollcommand=h_s.set
)
text_area.pack(padx=10, pady=10, expand=True, fill='both')
# Adding scrollability to text
v_s.config(command=text_area.yview)
h_s.config(command=text_area.xview)
window.mainloop()
Update
Or should I create 2 functions for one button? First function will change the label and text, and second function will run my_func().
As so often, the answer is very simple.
Try this:
#...
def select_folder() -> None:
"""
Tkinter function for button,
user can select folder.
"""
status.config(text="Status: Work in progress, please wait!") # switched lines here
path = filedialog.askdirectory()
text_area.insert(END, "Visited folders:\n")
my_function(path)
status.config(text="Status: Done!")
#...
Previously it did not work as intended, because filedialog.askdirectory() blocks the program-flow ( similarly to input() ).

Tkinter how to lock Text widget by checking checkbox?

I am new to programming and Tkinter. I want to DISABLED textbox when checkbox is pressed and open it NORMAL when box is not ticked. Here is my code:
from tkinter import *
root = Tk()
def lock_fields():
if check == True:
data.configure(state=DISABLED)
if check == False:
data.configure(state=NORMAL)
check = BooleanVar()
open_for_edit = Checkbutton(root, text="check the box for editing", variable=check,
onvalue=True, offvalue=False, command=lambda: lock_fields())
open_for_edit.pack()
check = check.get()
data = Text(root)
data.insert(END, "I would like to be able to edit this text only when checkbox is checked.")
data.pack()
root.mainloop()
It seems that for some reason the check-variable is always False when it enters to lock_fields function. I tried passing check argument to the method.
You're pretty close, only thing is that the check.get() line must be in the function. Also you don't need the lambda. Try this:
from tkinter import *
root = Tk()
def lock_fields():
if check.get():
data.configure(state=DISABLED)
else:
data.configure(state=NORMAL)
check = BooleanVar()
open_for_edit = Checkbutton(root, text="check the box for editing", variable=check, onvalue=True, offvalue=False, command=lock_fields)
open_for_edit.pack()
data = Text(root)
data.insert(END, "I would like to be able to edit this text only when checkbox is checked.")
data.pack()
root.mainloop()

Opening a new window using tkinter button

As you can see on my code I'm trying to open a new window with a button. Window opens but welcome message isn't showing like the way that I want.
It shows Welcome PY_VAR0 PY_VAR1. But I would like to show a name.
I've tried using return command to return variables from getvalue() function but it doesn't work.
def getvalue():
name.get()
surname.get()
def newwindow():
window.destroy()
window2 = tk.Tk()
label3 = tk.Label(text="Welcome {} {}".format(name,surname)).grid()
window2.mainloop()
button = tk.Button(window,text="Submit",command=getvalue and newwindow).grid(row=3,column=1)
window.mainloop()
I would like to open a new window with a welcome message.
You have to use .get() to get value from StringVar, IntVar, etc - name.get(), surname.get()
label3 = tk.Label(text="Welcome {} {}".format(name.get(), surname.get()))
label3.grid()
And remeber: To set value you will have to use variable.set(value) instead of variable = value
BTW: you have big mistake in this line (and others)
label3 = tk.Label(..).grid(..)
It assign None to label3 because grid()/pack()/place() return None
You have to do it in two steps
label3 = tk.Label(..)
label3.grid(..)
You can use messagebox to open a new window as well as print a welcome message. it is really simple.
from tkinter import Tk, Button
# Make sure to import messagebox like this, otherwise you might get issues
import tkinter.messagebox
def messagebox():
tkinter.messagebox.showinfo('title','Welcome!')
def main():
width, height = 500, 500
root = Tk()
root.geometry(f'{width}x{height}')
root.title('My window')
button = Button(root, width=150, height=70, command=messagebox)
button.pack()
root.mainloop()
if __name__ == "__main__":
main()
Please import messagebox the way it is shown, I am not sure why but tkinter does not like other ways.
What happens when you print(name + " " + surname)?
If those variables have the correct values maybe you should try rewriting your script a couple different ways, for example:
labelText = "Welcome " + name + " " + surname
label3 = tk.Label(text=labelText)

How to get the entry text and display in another entry?

I just want that when I type my name inside the entry box then appears in another entry with some add text. The idea is type in the entry below and after that it showed in the big entry.I was looking for this solution, but just found place in Label. I don't want in Label. The window is more big, must drag to show the entry. There's is a picture that i use in this script:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
cat = Entry(root)
cat.place(x=48, y=25, width= 350, height=140)
user = Entry(root)
user.place(x=75, y=550)
btn = Button(root, text='START')
btn.place(x=220, y=410)
root.mainloop()
#
Ok, It works the way you told me,thank you!
But now i'm facing another problem.
The problem is when i insert the function of the game in the second window. I tested in one window and it works, but when i place the function in the second window gives an error when i press the "Start" button:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
When i press reset button gives another error:
'''user_try = int(txt.get())
NameError: name 'txt' is not defined'''
So i know that is missing definition, but i don't know how to make a reference for this command that it's in the second window. Like i said running with just one window the program works.
Maybe i should make using class, i don't know, but i wish to make this way that i started. However if there's no other way to do as i'm doing, let's go.
I just simplify the script here, actualy the main script is more bigger, so my idea is when open the program, there is a window and the user read the instructions about the game and proceed open the second window. The window have pictures and some hidden buttons in the next picture, so there will be an interactivity with the environment.
The guess number is just the beggining. After that there will be new challeges.
I'm very excited doing this, but i'm stuck in this point. The part one i finished, the pictures, the hidden buttons it's exacly the way i want, but the challenge stops here in this problem.
from tkinter import *
from PIL import Image, ImageTk, ImageSequence
import random
from tkinter import messagebox
pc = random.randint(1,10)
def reset():
global pc
pc = random.randint(1,10)
cat['text'] = 'Ok! Lets Try Again!'
def openwin2():
win1.withdraw()
win2 = Toplevel()
win2.geometry('350x300+180+100')
win2.title('second window')
txt = Entry(win2)
txt.place(x=10,y=10)
cat = Label(win2,wraplength=300)
cat.place(x=10,y=50)
cat.config(text='Hi! I Am thinking a number between 1 and 10.')
btn = Button(win2,text='start',command=check)
btn.place(x=30, y=150)
btn2 = Button(win2, text='reset', command=reset)
btn2.place(x=110,y=150)
win2.mainloop()
def check():
user_try = int(txt.get())
if user_try < pc:
msg = 'Hmmmm... the number, which I thought of, is greater than this.'
elif user_try > pc:
msg = 'How about trying a smaller number ?!'
elif user_try == pc:
msg = 'Well Done! You guessed! It was %s the number!' % user_try
else:
msg = 'Something Went Wrong...'
cat['text'] = msg
win1 = Tk()
win1.title('First Window')
win1.geometry('350x300')
user = Label(win1,text='first window')
user.place(x=10,y=10)
btn1 = Button(win1,text='Open Window 2', command=openwin2)
btn1.place(x=10,y=50)
win1.mainloop()
There are multiple ways to do this in tkinter, here's a rework of your code using StringVar objects set to the textvariable properties of your Entry objects:
import tkinter as tk
def doit():
out_string.set("Hello " + in_string.get())
root = tk.Tk()
in_string = tk.StringVar()
out_string = tk.StringVar()
cat = tk.Entry(root, textvariable=in_string)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root, textvariable=out_string)
user.place(x=20, y=75)
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
Per #Mike-SMT, here's a different approach using Entry.get() and Entry.insert(). It augments the text when the user clicks the button:
import tkinter as tk
def doit():
user.insert(tk.END, cat.get())
root = tk.Tk()
cat = tk.Entry(root)
cat.place(x=20, y=25, width=100)
user = tk.Entry(root)
user.place(x=20, y=75)
user.insert(0, "Hello ")
btn = tk.Button(root, text='START', command=doit)
btn.place(x=20, y=150)
root.mainloop()
However, you'll see that subsequent button clicks keep appending the text. When working with Entry.insert(), you need to work with Entry.delete() and/or other Entry methods to properly manipulate the text.

Python tkinter 8.5 - How do you change focus from main window to a pop up window?

I'm new to tkinter and have a rather simple question. I would like to change focus from the first window, root, to the txt window after it pops up. I would also like the "OK" button to be focused as well. Of course, the idea is for the user to just be able to hit enter when they see this error. I'm terribly confused after various attempts with focus(), focus_set(), and takefocus. I'm not finding the documentation for this particularly helpful.
Below is my code:
from tkinter import *
from tkinter import ttk
def close(self):
self.destroy()
def browse(*args):
fileName = filedialog.askopenfilename()
guiInputFile_entry.insert(0, fileName)
return fileName
def formatInput(*args):
if guiInputFile.get()[-4:] != ".txt": #checks for correct file extension (.txt)
txt = Tk()
txt.title("Error")
txtFrame = ttk.Frame(txt, padding="30 30 30 30")
txtFrame.grid(column=0, row=0, sticky=(N,W,E,S))
txtFrame.columnconfigure(0, weight=1)
txtFrame.rowconfigure(0, weight=1)
ttk.Label(txtFrame, text = "Please enter a .txt file.\n").grid(column=2, row=1)
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt)).grid(column=2, row=2)
return
root = Tk()
root.title("Cost Load Formatter")
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N,W,E,S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
guiInputFile = StringVar()
guiInputFile_entry = ttk.Entry(mainframe, width=100, textvariable=guiInputFile)
guiInputFile_entry.grid(column=1, row=2, stick=(W,E))
ttk.Label(mainframe, text="Please enter the full filepath of the .txt file you wish to format:").grid(column=1, row=1)
browseButton = ttk.Button(mainframe, text="Browse...", underline=0, command=browse).grid(column=2, row=2, sticky=W)
formatButton = ttk.Button(mainframe, text="Format", underline=0, command= lambda: formatInput(guiInputFile)).grid(column=1, row=3)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
guiInputFile_entry.focus()
root.mainloop()
Thank you for any light you can shed.
You're on the right track.
Firstly, you should only ever have one instance of Tk at a time. Tk is the object that controls the tkinter application, it just so happens that it also shows a window. Whenever you want a second window (third, fourth, etc.) you should use Toplevel. You can use it as you have used Tk, just pass it root:
txt = Toplevel(root)
It is just missing things like mainloop.
Secondly grid and pack do not return anything. So for example:
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt)).grid(column=2, row=2)
Should be:
okButton = ttk.Button(txtFrame, text = "OK", command = lambda: close(txt))
okButton.grid(column=2, row=2)
But you should have been getting an error if that was causing you problems.
So to answer your main question, as you do with the Entry at the bottom you just call focus on the appropriate widget. focus_set does exactly the same, in fact if you look in Tkinter.py you will find focus_set is the name of the method, and focus is just an alias.
This will give the widget focus when the application has focus. If the application is not in focus there are ways to force it into the focus, but it is considered impolite and you should let the window manager control that.
Instead of making a seperate Tk Window, you could use the built in tkmessagebox. This will give the window and OK button focus right out of the box.
Something like this:
tkMessageBox.showinfo("Warning","Please enter a .txt file.")
http://www.tutorialspoint.com/python/tk_messagebox.htm
Also, note I wrote this in Python 2.7, the syntax may be slightly different for Python 3, but the functionality should be the same.

Categories

Resources