My problem is that I want my code to take an entry from the user,
then the value that the user entered will be displayed on the toplevel page pf the previous class.
I have searched quite a bit but none of the solution worked for me.
So could any one of you generously tell me how I can change my code so that I can actually display the value entered by the user in the toplevel page?
Many thanks<3
import Tkinter as tk
class Demo2:
def __init__(self, master):
self.master = master
self.quitButton = tk.Button(self.master, text = 'Quit', width = 25, command = self.close_windows)
self.goButton = tk.Button(self.master, text = "Go", command = self.window_one)
global EnteredNumber
self.EnteredNumber = tk.IntVar()
self.entry = tk.Entry(self.master,textvariable=self.EnteredNumber)
VertexNumber = self.EnteredNumber.get()
self.goButton.pack()
self.entry.pack()
self.quitButton.pack()
def close_windows(self):
self.master.destroy()
def window_one(self):
self.window_one = tk.Toplevel(self.master)
self.app = Demo3(self.window_one)
class Demo3():
def __init__(self, master):
self.master = master
self.label1 = tk.Label(self.master, text=EnteredNumber)
self.label = tk.Label(self.master, text="Hi")
self.label.pack()
self.label1.pack()
def main():
root = tk.Tk()
app = Demo2(root)
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.mainloop()
if __name__ == '__main__':
main()
Send the value of the Entry through to the __init__ of Demo3()
First the changes to window_one():
def window_one(self):
enterednumber = self.entry.get() # Grab the value in the Entry
self.window_one = tk.Toplevel(self.master)
self.app = Demo3(self.window_one, enterednumber) # Send it to Demo3 as an argument
And then Demo3()
class Demo3():
def __init__(self, master, enterednumber): # Reconfigure __init__ to accept the new arg
self.master = master
self.label1 = tk.Label(self.master, text=enterednumber)
self.label = tk.Label(self.master, text="Hi")
self.label.pack()
self.label1.pack()
Related
I have a custom Entry "self.name_e" on the second window "Demo 2" but anytime I run the code the custom entry only shows up on the first window "Demo 1"...
self.name_e is used to receive the entry on Window 2 "Demo 2"
The AutocompleteEntry is the custom Entry class that is used by windows two
How do I fix this?
import tkinter as tk
#To shorten the code for perfect readability I chose to remove the content of the AutocompleteEntry class
class AutocompleteEntry(Entry):...
class Demo1:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
self.master.geometry("1366x768+0+0")
self.button1.pack()
self.frame.pack()
def new_window(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Demo2(self.newWindow)
class Demo2:
def __init__(self, master):
self.master = master
autocompleteList = [ 'Milo tin', 'Shito small' ]
def matches(fieldValue, acListEntry):
pattern = re.compile(re.escape(fieldValue) + '.*', re.IGNORECASE)
return re.match(pattern, acListEntry)
self.frame = tk.Frame(self.master)
self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
self.master.geometry("1366x768+0+0")
self.quitButton.pack()
self.frame.pack()
#AutocompleteEntry is a custom Entry which is also a class on it own
self.name_e = AutocompleteEntry(autocompleteList, listboxLength=10, width=20, font=('arial 18 bold'), matchesFunction=matches)
self.name_e.place(x=350, y=150)
def close_windows(self):
self.master.destroy()
def main():
root = tk.Tk()
app = Demo1(root)
root.mainloop()
if __name__ == '__main__':
main()
I am trying to return a value from an Entry widget from another class.
My idea is, when the user has logged in successfully, the welcome screen will show the username that has just logged in.
I have tried using this:
self.userLogged = Label(main, text = self.entry_username.get())
self.userLogged.pack()
i tried linking >self.entry.entry_username.get() from the login class. But here is the error code:
AttributeError: 'App' object has no attribute 'entry_username'
Where I'm I going wrong?
Here is the full code:
from tkinter import *
import tkinter.ttk as ttk
class App():
def __init__(self,master):
notebook = ttk.Notebook(master)
notebook.pack(expand = 1, fill = "both")
#Frames
main = ttk.Frame(notebook)
notebook.add(main, text='Welcome Screen')
self.userLogged = Label(main, text = self.entry_username.get())
self.userLogged.pack()
###################################################################################################################################
##USERS##
###################################################################################################################################
class login(Frame):
def __init__(self, master):
super().__init__(master)
self.label_username = Label(self, text="Username: ",font=("bold",16))
self.label_password = Label(self, text="Password: ",font=("bold",16))
self.entry_username = Entry(self, font = ("bold", 14))
self.entry_password = Entry(self, show="*", font = ("bold", 14))
self.label_username.grid(row=0, sticky=E)
self.label_password.grid(row=1, sticky=E)
self.entry_username.grid(row=0, column=1)
self.entry_password.grid(row=1, column=1)
self.logbtn = Button(self, text="Login", font = ("bold", 10), command=self._login_btn_clicked)
self.logbtn.grid(columnspan=2)
self.pack()
def _login_btn_clicked(self):
# print("Clicked")
username = self.entry_username.get()
password = self.entry_password.get()
# print(username, password)
account_list = [line.split(":", maxsplit=1) for line in open("passwords.txt")]
# list of 2-tuples. Usersnames with colons inside not supported.
accounts = {key: value.rstrip() for key, value in account_list}
# Convert to dict[username] = password, and slices off the line ending.
# Does not support passwords ending in whitespace.
if accounts[username] == password:
self.label_username.grid_forget()
self.label_password.grid_forget()
self.entry_username.grid_forget()
self.entry_password.grid_forget()
self.logbtn.grid_forget()
self.pack_forget()
app = App(root)
else:
print("error")
root = Tk()
root.minsize(950, 450)
root.title("test")
lf = login(root)
root.mainloop()
When working with multiple classes in tkinter it is often a good idea to use class inherancy for the main window and frames. This allows us to use self.master to interact between classes.
That said you have a few things to change. You are using self where it is not needed and you should be doing import tkinter as tk to prevent overwriting of methods.
I have added a class to your code so we use one class for the root window. Then use one class for the login screen and then use one class for the frame after login.
import tkinter as tk
import tkinter.ttk as ttk
class NotebookFrame(tk.Frame):
def __init__(self, username):
super().__init__()
notebook = ttk.Notebook(self)
notebook.pack(expand=1, fill="both")
main = ttk.Frame(notebook)
notebook.add(main, text='Welcome Screen')
tk.Label(main, text=username).pack()
class Login(tk.Frame):
def __init__(self):
super().__init__()
tk.Label(self, text="Username: ", font=("bold", 16)).grid(row=0, sticky='e')
tk.Label(self, text="Password: ", font=("bold", 16)).grid(row=1, sticky='e')
self.entry_username = tk.Entry(self, font=("bold", 14))
self.entry_password = tk.Entry(self, show="*", font=("bold", 14))
self.entry_username.grid(row=0, column=1)
self.entry_password.grid(row=1, column=1)
tk.Button(self, text="Login", font=("bold", 10), command=self.master._login_btn_clicked).grid(columnspan=2)
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("test")
self.minsize(950, 450)
self.login_frame = Login()
self.login_frame.pack()
def _login_btn_clicked(self):
username = self.login_frame.entry_username.get()
password = self.login_frame.entry_password.get()
account_list = [line.split(":", maxsplit=1) for line in open("passwords.txt")]
accounts = {key: value.rstrip() for key, value in account_list}
if accounts[username] == password:
self.login_frame.destroy()
NoteFrame = NotebookFrame(username)
NoteFrame.pack()
else:
print("error")
if __name__ == "__main__":
App().mainloop()
Firstly, you should change class name from class login(Frame) to class Login(Frame).
Before fixing it, you called the login function from App, but you need to call Login class and use it.
class App:
def __init__(self, master):
notebook = ttk.Notebook(master)
notebook.pack(expand=1, fill="both")
# Frames
main = ttk.Frame(notebook)
notebook.add(main, text='Welcome Screen')
# `entry_username.get()` method is owned by the Login class,
# so you need to call from not `self(App class)` but `login(Login class)`.
login = Login(master) # Call Login class
self.userLogged = Label(main, text=login.entry_username.get())
self.userLogged.pack()
With this fix, I could call the Welcome screen.
I'm trying to create a modular class ( for some gui buttons ).
CoreButton should consist of most methods for a common button, including tk frame.
Goal is to inheret CoreButton - and to use its frame to build rest of button's GUI - it does not appear.
any help will be appriciated
class CoreButton(ttk.Frame):
def __init__(self, master,nickname, hw_in=[], hw_out=[],ip_in='', ip_out='', sched_vector=[]):
ttk.Frame.__init__(self, master)
self.master = master
if ip_in == '': ip_in = ip_out # in case remote input is not defined
self.grid()
#####Rest of code
and class that inherits:
class ToggleBut2(CoreButton):
def __init__(self, master, hw_in=[], hw_out=[],ip_in='', ip_out='', sched_vector=[]):
CoreButton.__init__(self, master, nickname="JOHM", hw_in=hw_in, hw_out=hw_out, ip_in=ip_in, ip_out=ip_out, sched_vector=sched_vector)
self.master = master
def build_gui(self, nickname='babe', height=3, width=13):
self.button = tk.Checkbutton(self, text=nickname, variable=self.but_var, indicatoron=0, height=height, width=width, command=self.sf_button_press)
self.button.grid(row=0, column=0)
I don't know what you try to do but I would do something like this
I don't use self.grid() inside class, so outside class I can use tb1.pack() or tb1.grid() depends on which layout manager I use in window.
In __init__ I execute self.build_gui() so I don't have to do it manually, but now all classes have to create self.build_gui() without arguments.
I add Label only for test - to display "selected"/"not selected". You don't need it.
import tkinter as tk
from tkinter import ttk
class CoreButton(ttk.Frame):
def __init__(self, master, nickname, hw_in=None, hw_out=None, ip_in=None, ip_out=None, sched_vector=None):
ttk.Frame.__init__(self, master)
self.nickname = nickname
self.hw_in = hw_in
if self.hw_in is None:
self.hw_in = []
#self.hw_in = hw_in or []
self.hw_out = hw_out
if self.hw_out is None:
self.hw_out = []
#self.hw_out = hw_out or []
self.ip_out = ip_out
self.ip_in = ip_in
if self.ip_in is None:
self.ip_in = self.ip_out # in case remote input is not defined
#self.ip_in = hw_in or self.ip_out
self.sched_vector = sched_vector
if sched_vector is None:
sched_vector = []
#self.sched_vector = sched_vector or []
self.build_gui() # <--- to build it automatically
def build_gui(self):
# you will overide it in child widgets
raise NotImplementedError('You have to override method build_gui()')
class ToggleBut2(CoreButton):
def __init__(self, master, hw_in=None, hw_out=None, ip_in=None, ip_out=None, sched_vector=None, height=3, width=13):
self.height = height
self.width = width
# `self.but_var` is used in `build_gui` so it has to be created before `__init__` which executes `build_gui`
# or create it directly in `build_gui`
#self.but_var = tk.StringVar()
CoreButton.__init__(self, master, "JOHM", hw_in, hw_out, ip_in, ip_out, sched_vector)
def build_gui(self, nickname='babe'):
self.but_var = tk.IntVar()
self.button = tk.Checkbutton(self, text=self.nickname, variable=self.but_var, indicatoron=0, height=self.height, width=self.width, command=self.sf_button_press)
self.button.grid(row=0, column=0)
self.label = tk.Label(self, text='[not selected]')
self.label.grid(row=1, column=0)
def sf_button_press(self):
print(self.but_var.get())
if self.but_var.get() == 0:
self.label['text'] = '[ not selected ]'
else:
self.label['text'] = '[ selected ]'
# --- main ---
root = tk.Tk()
tb1 = ToggleBut2(root, height=1, width=10)
tb1.pack()
tb2 = ToggleBut2(root, height=3, width=30)
tb2.pack()
tb2 = ToggleBut2(root, height=5, width=50)
tb2.pack()
root.mainloop()
I am trying to make a GUI for my program but I have changed my code a lot and I saw that GUI misses one frame but it was fine before.
Could anyone help me and tell why a frame with a button does not appear on the bottom?
Whole "button_part" object does not appear.
from tkinter import *
import tkinter as tk
import os
import glob
BOUNDS = ["Last week", "Last 2 weeks", "Last 3 weeks"]
class settings_part:
path_to_copy = 0
def __init__(self, master, update_func):
path_to_copy = StringVar()
settings_frame = Frame(master, background="")
settings_frame.pack(side=TOP, fill=X)
date_bound = StringVar()
date_bound.set(BOUNDS[1])
date_option = OptionMenu(settings_frame, date_bound, *BOUNDS, command=update_func)
date_option.config(background="#732c30")
date_option.config(foreground="white")
date_option.config(bd=0)
date_option.pack(side=LEFT, padx=5, pady=5)
path_to_copy.set("~/Python/usun")
box_with_path = Entry(settings_frame, textvariable=path_to_copy)
box_with_path.pack(side=RIGHT, padx=5, pady=5)
# s = path_to_copy.get()
class songs_part:
def __init__(self, master, root):
self.songs_frame = Frame(master)
self.update_songs(root.list_of_songs)
self.songs_frame.pack()
def update_songs(self, l):
for song in l:
c = Checkbutton(self.songs_frame, text=song[0], variable=song[1])
c.pack()
class button_part:
def __init__(self, master, copyFunc):
self.button_frame = Frame(master)
btn_image = PhotoImage(file="copybtn.png")
self.copy_button = Button(self.button_frame, command=copyFunc, text="Copy",
image=btn_image, highlightthickness=0, bd=0, activebackground="#732c30")
self.copy_button.pack()
class App:
def __init__(self):
root = Tk()
root.title("Copying songs")
root.geometry("500x500")
root.option_add("*Font", "Calibra")
back_image = PhotoImage(file="back.png")
self.window = Label(root, image=back_image)
self.window.pack(fill="both", expand="yes")
self.list_of_songs = list()
self.make_list_of_songs()
self.set_part = settings_part(self.window, self.update_list)
self.son_part = songs_part(self.window, self)
self.but_part = button_part(self.window, self.copy_songs)
root.mainloop()
def make_list_of_songs(self):
owd = os.getcwd()
os.chdir("/home/stanek/Music/usun")
for file in glob.glob("*.mp3"):
self.list_of_songs.append([file, tk.IntVar()])
os.chdir(owd)
def copy_songs(self):
for s in self.list_of_songs:
print(s)
def update_list(self, arg):
print("updating list with songs from " + arg)
self.son_part = songs_part(self.window, self)
if __name__ == '__main__':
App()
You never pack the button frame.
I'm making a quiz app with tkinter and i want each question in a new window, but after I create a new window i can't figure out how to destroy the previous window. Here is a rough simplified excerpt of my code:
from tkinter import *
class q1:
def __init__(self, master):
self.master = master
Label(self.master, text='What is 3 + 3?').grid()
self.option_1 = Button(self.master, text='5', command = self.incorrect)
self.option_1.grid()
self.option_2 = Button(self.master, text='6', command = self.correct)
self.option_2.grid()
def correct(self):
self.option_1.config(state=DISABLED)
self.option_2.config(state=DISABLED)
Label(self.master, text='Correct').grid()
Button(self.master, text='Next Question', command = self.nextq).grid()
def incorrect(self):
self.option_1.config(state=DISABLED)
self.option_2.config(state=DISABLED)
Label(self.master, text='Incorrect').grid()
Button(self.master, text='Next Question', command = self.nextq).grid()
def nextq(self):
q2(Toplevel(self.master))
class q2:
def __init__(self, master):
self.master = master
Label(self.master, text='Question 2').grid()
def window():
root = Tk()
q1(root)
root.mainloop()
if __name__ == '__main__':
window()
UPDATED VERSION
from Tkinter import *
import random
class Ask:
def __init__(self, parent,question,right,wrong):
self.answer=right
self.top=top=Toplevel(parent)
Label(self.top, text=question,width=25).grid()
a1=random.choice([right,wrong])
self.option_1 = Button(self.top, text=a1, width=25,command = lambda: self.check(1))
self.option_1.grid()
a2=right
if a1==right:
a2=wrong
self.option_2 = Button(self.top, text=a2, width=25, command = lambda: self.check(2))
self.option_2.grid()
def check(self,pressed):
if pressed==1:
ans=self.option_1['text']
else:
ans=self.option_2['text']
if ans==self.answer:
self.correct()
else:
self.incorrect()
def correct(self):
self.option_1.config(state=DISABLED)
self.option_2.config(state=DISABLED)
Label(self.top, text='Correct').grid()
Button(self.top, text='Next Question', command = self.top.destroy).grid()
def incorrect(self):
self.option_1.config(state=DISABLED)
self.option_2.config(state=DISABLED)
Label(self.top, text='Incorrect').grid()
Button(self.top, text='Next Question', command = self.top.destroy).grid()
class QUIZ:
def __init__(self, questionsdict):
self.root=Tk()
self.root.withdraw()
self.questions(questionsdict)
self.root.deiconify()
c=Button(self.root, text='Click me to exit', command=self.root.destroy, width=30).grid(row=2, sticky='ew')
Label(self.root, text='Quiz is Complete', width=30, background='red').grid(row=0, sticky='ew')
mainloop()
def questions(self,questionsdict):
for k in questionsdict.keys():
right=questionsdict[k][0]
wrong=questionsdict[k][1]
b=Ask(self.root, k, right,wrong )
self.root.wait_window(b.top)
put quiz questions in a dictionary in the format: {question:[correctchoice,incorrectchoice]} and use that as the parameter when calling the Question Class
questions={'What is 3+3':['6','8'], 'What is the capital of Alaska': ['Juno','Anchorage']}
QUIZ(questions)