I am working through an Oreilly Tutorial on tkinter, but the code provided in the tutorial doesn't work for me. The "Choose one" message doesn't show, instead it shows: PY_VAR0. When I click the hello button nothing happens. When I click the goodbye button the window closes as expected but no message is shown.
Of note, prior I had:
def say_hello(self):
self.label.configure(text="Hello World!")
def say_goodbye(self):
self.label.configure(text="Goodbye! \n (Closing in 2 seconds)")
self.after(2000, self.destroy)
And received an attribute error: attributeerror: '_tkinter.tkapp' object has no attribute 'label' site:stackoverflow.com.
I am uncertain what is wrong as I have followed the example explicitly in both cases.
My code is below:
import tkinter as tk
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.title('Hello Tkinter')
self.label_text = tk.StringVar()
self.label_text.set("Choose One")
label = tk.Label(self, text=self.label_text)
label.pack(fill=tk.BOTH, expand=1, padx=100, pady=30)
hello_button = tk.Button(self, text='Say Hello',
command=self.say_hello)
hello_button.pack(side=tk.LEFT, padx=(20, 0), pady=(0, 20))
goodbye_button = tk.Button(self, text ='Say Goodbye',
command=self.say_goodbye)
goodbye_button.pack(side=tk.RIGHT, padx=(0, 20), pady=(0, 20))
def say_hello(self):
self.label_text.set("Hello World!")
def say_goodbye(self):
self.label_text.set("Goodbye! \n (Closing in 2 seconds)")
self.after(2000, self.destroy)
if __name__ == "__main__":
window = Window()
window.mainloop()
You need to set the label textvariable=self.label_text instead of text=self.label_text
import tkinter as tk
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.title('Hello Tkinter')
self.label_text = tk.StringVar()
self.label_text.set("Choose One")
label = tk.Label(self, textvariable=self.label_text)
label.pack(fill=tk.BOTH, expand=1, padx=100, pady=30)
hello_button = tk.Button(self, text='Say Hello',
command=self.say_hello)
hello_button.pack(side=tk.LEFT, padx=(20, 0), pady=(0, 20))
goodbye_button = tk.Button(self, text ='Say Goodbye',
command=self.say_goodbye)
goodbye_button.pack(side=tk.RIGHT, padx=(0, 20), pady=(0, 20))
def say_hello(self):
self.label_text.set("Hello World!")
def say_goodbye(self):
self.label_text.set("Goodbye! \n (Closing in 2 seconds)")
self.after(2000, self.destroy)
if __name__ == "__main__":
window = Window()
window.mainloop()
Related
So before you question the code, im just trying to learn tkinter a bit more so i though this be best way haha.
I am currently stuck on the web input, everytime i input a website it comes as "https://%21browser.%21text!" and i dont know why. Random web works but it doesnt work as inputting it.
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Text(self, height=1, width=57)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = "https://{}".format(self.webinput)
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
I have made some change, now it works very well
import webbrowser as wb
from tkinter import *
from tkinter import ttk
import tkinter as tk
import ctypes, random, time
class Browser(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.start()
def start(self):
global webinput
self.title = Label(self, text="Web Shortcut", fg="purple", font="Kokila 20 bold")
self.title.pack(fill=BOTH)
self.webinput = Entry(self)
self.webinput.pack(side=TOP, fill=BOTH, pady=30, padx=30)
self.openweb = Button(self, height=2, width=20, text="Open Web", bg="gray", fg="lightgreen", command=self.web)
self.openweb.pack(side=LEFT, padx=10)
self.random = Button(self, height=2, width=20, text="Random Web", bg="gray", fg="lightgreen", command=self.randomweb)
self.random.pack(side=LEFT, padx=5)
self.exit = Button(self, height=2, width=20, text="Exit", bg="gray", fg="lightgreen", command=exit)
self.exit.pack(side=LEFT, padx=5)
def web(self):
try:
self.sites = f"https://{self.webinput.get()}"
if self.sites:
wb.open(self.sites)
except Exception as e:
ctypes.windll.user32.MessageBoxW(0, str(e), "CRASHED", 0)
def randomweb(self):
self.websites = [
"www.facebook.com",
"www.google.com",
"www.youtube.com",
"www.amazon.co.uk"
]
self.sites = random.choice(self.websites)
self.visit = "https://{}".format(self.sites)
wb.open(self.visit)
if __name__ == "__main__":
root = Tk()
root.title("Web Shortcut")
root.resizable(False, False)
root.geometry("500x200")
app = Browser(master=root)
app.mainloop()
root.destroy()
Hope it helps. (●'◡'●)
I'm new to python and tkinter GUI, I need to access button click action from the main function, is there any possibility to do that? any way I can access it in click function inside the class that I have comment it. what is the correct method to do it? thank you
from tkinter import *
class Youtube:
def __init__(self,master):
self.master = master
master.title('Youtube_Downloder')
self.screen = Entry(master, state='normal', width=25, background="White", foreground="blue",
font=('Arial', 12))
self.screen.grid(row=1, column=0, columnspan=4, padx=5, pady=5)
self.layout = Label(master, text='Past the Link below', font=('Arial', 16),foreground="red")
self.layout.grid(row=0, column=1)
self.create_button('Add Link',1,30)
def create_button(self,val,row,column,width=12):
button = Button(self.master, text=val, width=width, command=lambda: self.click(val))
return button.grid(row=row,column=column)
def click(self,clicked_button=None):
if clicked_button == 'Add Link':
#self.create_label(self.screen.get(), 3, 1) #this methord working
return 'Add Link'
def create_label(self,text,row,column,font=('Arial',8)):
return Label(self.master, text=text, font=font).grid(row=row, column=column)
def main():
root = Tk()
my_gui = Youtube(root)
if my_gui.click() == 'Add Link':
my_gui.create_label(my_gui.screen.get(), 3, 1)
root.mainloop()
if __name__ == '__main__':
main()
I'm assuming it could be this button:
def create_button(self,val,row,column,width=12):
button = Button(self.master, text=val, width=width, command=lambda: self.click(val))
return button.grid(row=row,column=column)
Change button to self.button. When you've done that you can access it in main by using my_gui.button.
If you ever decide to use an mvc model, this will be the approach as well.
I'm using ttk, for my GUI. I know that it is also a very simple question ... I am trying to change the background color of the main window.
I tried to change the theme, because I am working on a Mac, (and Python 3.5) to avoid the problem with the theme 'aqua', which is the default.I've been reading about several solutions like these questions which are about the same problem... These are the numbers of the questions:
54476511,
38712352,
47327266,
23750141.
But, I haven't Solve the problem, yet.
Here it's my code.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self,master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
Style().theme_use("classic")
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(bg='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
Any Suggestions would be appreciated.
Create a style then apply it.
from tkinter.scrolledtext import *
from tkinter import Tk, BOTH, W, N, E, S, messagebox, END
from tkinter.ttk import Button, Label, Style, Frame
class Example(Frame):
def __init__(self, master):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Example")
# create a new style
self.style = Style()
# configure it to the background you want
self.style.configure('My.TFrame', background='#0059b3')
#Style().theme_use("classic")
# apply it
self.config(style='My.TFrame')
self.pack(fill=BOTH, expand=1)
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
self.txt_Pad = ScrolledText(self)
self.txt_Pad.grid(row=1, column=0, columnspan=2, rowspan=4, padx=5, sticky=E+W+S+N)
self.txt_Pad.insert(END,'Type your info here')
btn_save = Button(self, text="Save", command=self.save_command)
btn_save.grid(row=1, column=3)
btn_close = Button(self, text="Close", command=self.onClose)
btn_close.grid(row=2, column=3, pady=4)
btn_help = Button(self, text="Help", command=self.about_command)
btn_help.grid(row=5, column=0, padx=5)
def onClose(self):
self.master.destroy()
def about_command(self):
msb = messagebox.showinfo("About", "\"Insert a useful tip Here\"")
def save_command(self):
print('Your info it\'s save now')
def open_command(self):
print('Choose your File')
def main():
root = Tk()
root.geometry("350x300+300+300")
root.configure(background='#0059b3')
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
I left comments at the parts I changed.
Passing variables between frames in Tkinter
Followed the multiframe class example in:
from Switch between two frames in tkinter
by Bryan Oakley / Steven M. Vascellaro
Everything works fine within each frame, but trying to pass a Frame StartPage-entry text into the Frame PageTwo-scroll requires syntax in :
txtScroll(txt): ??????scroll.insert(tk.INSERT,scrolltxt)
I do not get.
BTW:
Tried following the original solution to:
Passing variables between frames in Tkinter
by adding
def __init__(self, master,controller, uploadPage=None):
self.controller = controller
self.uploadPage = PageTwo
To no avail ??????
# from https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
# by Bryan Oakley / Steven M. Vascellaro
import tkinter as tk # python 3
from tkinter import ttk, font as tkfont, scrolledtext # python 3
from tkinter.ttk import *
#definitions ----------------------
def txtClicked(txt):
res = "Entry text " + txt.get()
print(res)
def txtScroll(txt):
# Problem with output to scroll in different class ?
scroll.insert(tk.INSERT,scrolltxt)
def scrollInsert(scroll,scrolltxt):
scroll.insert(tk.INSERT,scrolltxt)
#Frame class ----------------------
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.replace_frame(StartPage)
def replace_frame(self, frame_class):
"""Destroys current frame and replaces i with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master, uploadPage=None):
tk.Frame.__init__(self, master)
#self.controller = controller
self.uploadPage = PageTwo
tk.Label(self, text="This is the start page").pack(side="top", fill="x", pady=10)
# Entry
txt = Entry(self,width=10)
txt.pack(side="top", fill="x", pady=10)
btn = Button(self, text="Get Entry", command=lambda: txtClicked(txt)).pack()
btn = Button(self, text="Scroll Output", command=lambda: txtScroll(txt)).pack()
#-------------
tk.Button(self, text="Open page one", command=lambda: master.replace_frame(PageOne)).pack()
tk.Button(self, text="Open page two", command=lambda: master.replace_frame(PageTwo)).pack()
class PageOne(tk.Frame):
def __init__(self, master, uploadPage=None):
tk.Frame.__init__(self, master)
#self.controller = controller
self.uploadPage = PageTwo
tk.Label(self, text="This is page one").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Return to start page", command=lambda: master.replace_frame(StartPage)).pack()
class PageTwo(tk.Frame):
def __init__(self, master, uploadPage=None):
tk.Frame.__init__(self, master)
#self.controller = controller
print ("tk.Frame: ", tk.Frame )
print ("self: ", self )
print ("master: ", master )
# scrolledtext
scroll = scrolledtext.ScrolledText(self,width=40,height=10)
scroll.pack(side="bottom", padx=10, pady=10)
scrolltxt = "Print scroll stuff..."
btn = Button(self, text="Print scroll", command=lambda: scrollInsert(scroll,scrolltxt)).pack()
#-------------
tk.Label(self, text="This is page two").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Return to start page", command=lambda: master.replace_frame(StartPage)).pack()
#Tkinder Main ----------------------
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
This question already has answers here:
No input possible after tk
(2 answers)
Closed 4 years ago.
I'm using the following code to open a file, read its lines into a list and filter them using a substring from an Entry:
def get_entries(self):
"""
Open a file and load entries into a list.
"""
try:
# self.file_name = "p1.py"
self.file_name = askopenfilename(title="Open file")
self.file_handle = open(self.file_name, "r")
except IOError:
messagebox.showinfo("Info", "No file has been openned.")
self.destroy()
else:
self.entry_list = self.file_handle.readlines()
self.update_list()
def update_list(self, *args):
"""
Update the list after each editing of the search filter
"""
search_term = self.search_var.get()
self.lbox.delete(*self.lbox.get_children())
for index, item in enumerate(self.entry_list):
if search_term.lower() in item.lower():
self.lbox.insert('', END, values=(index, item))
Why does it work fine using self.file_name = "p1.py" but using askopenfilename() disables editing the Entry?
Minimizing and restoring the window with the Entry fixes the problem.
I'm using PyCharm on Windows 10
Here is the rest of the code for reference:
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from tkinter.filedialog import askopenfilename
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.file_name = ""
self.file_handle = ""
self.entry_list = None
self.search_label = Label(self, text="Filter: ")
self.search_var = StringVar()
self.search_var.trace("w", self.update_list)
self.search_entry = Entry(self, textvariable=self.search_var)
self.lbox = ttk.Treeview(self, columns=('indices', 'entries'), displaycolumns='entries', show='headings')
self.lbox.heading('entries', text="Entries", anchor="w")
self.confirm = Button(self, text="Confirm", width=10, command=self.confirm_action)
self.cancel = Button(self, text="Cancel", width=10, command=quit)
self.search_label.grid(row=0, column=0, sticky=E, padx=12, pady=5)
self.search_entry.grid(row=0, column=1, sticky=W, columnspan=4, pady=5)
self.lbox.grid(row=1, column=0, columnspan=3, sticky=(N, W, S, E), padx=12, pady=5)
self.cancel.grid(row=2, column=0, pady=5)
self.confirm.grid(row=2, column=1, sticky=W, padx=12, pady=5)
self.grid_columnconfigure(0, weight=1, uniform="u")
self.grid_columnconfigure(1, weight=1, uniform="u")
self.grid_columnconfigure(2, weight=4, uniform="u")
self.get_entries()
def get_entries(self): ...
def update_list(self, *args): ...
def confirm_action(self): ...
root = Tk()
root.title('Filter Listbox Test')
app = Application(master=root)
app.mainloop()
This seems to be a problem due to calling the askfilename before the root window is drawn. As a workaround you can add self.update() before you call askopenfilename.
class Application(Frame):
def __init__(self, master=None):
# ... stuff ...
self.update()
self.get_entries()
I'll file a bug report about this right now.