I try to make a user interface where the user gives his name in a entry-box, when i try to print the name variable something goes wrong en PY_VAR gets printed.
import tkinter as tk
class TestApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.geometry('400x500')
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.grid()
def save(self,var1name):
print(var1name)
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
var1name = tk.StringVar()
#Entry of basic information
tk.Label(self, text="Please enter setup").grid(row=0, column=1, sticky="W")
tk.LabelFrame(self, text="labelframe").grid()
tk.Label(self, text="Name: ").grid(row=1, column=0, sticky="W")
tk.Entry(self,textvar=var1name).grid(row=1, column=2, sticky="W")
tk.Button(self, text="Set",
command=lambda: master.save(var1name)).grid(row=9, column=1, sticky="E")
#tk.Button(self, text="Next",
#command=lambda: master.switch_frame(PageOne)).grid(row=9, column=2, sticky="E")
if __name__ == "__main__":
app = TestApp()
app.mainloop()
i expected a name printed on the Python interface but it printed PY_VAR instead
var1name is a reference to a Tkinter.StringVar object. You need to call its get method to access the value that it represents, for example:
print (var1name.get())
The get method returns the current value of the variable, as a Python
object.
In your code:
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
var1name = tk.StringVar()
# Entry of basic information
tk.Label(self, text="Please enter setup").grid(row=0, column=1, sticky="W")
tk.LabelFrame(self, text="labelframe").grid()
tk.Label(self, text="Name: ").grid(row=1, column=0, sticky="W")
tk.Entry(self, textvar=var1name).grid(row=1, column=2, sticky="W")
tk.Button(self, text="Set",
command=lambda: master.save(var1name.get())).grid(row=9, column=1, sticky="E")
Related
I have created Frame with Entry widget to ask user to input his Username and select a team, that he want to join in and also I have created an OpenMenu Widget with 4 teams that user can join.
I want to know, how to assign list to OpenMenu variations as a list. For example: Selection "Team 1" = team1Members etc.
Also I want to know, how to assign data from Entry Widget to appropriate list. For example, if user have selected "Team 1", his username will append to team1Members list.
from tkinter import *
import tkinter.ttk as ttk
team1Members = []
team2Members = []
team3Members = []
team4Members = []
class CollegeApp(Tk):
def __init__(self):
Tk.__init__(self)
container = ttk.Frame(self)
container.pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (StartPage, selectionPage, TeamsPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.startMenu()
def startMenu(self):
heading = Label(self, text="College Tournament Points\n Count Software",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=240, pady=40)
start_Btn = Button(self, text="Start", font="Arial 16", width=8,
command=lambda: self.controller.show_frame(selectionPage))
start_Btn.grid(row=1, column=0, padx=30, pady=5)
exit_Btn = Button(self, text="EXIT", font="Arial 16", width=8,
command=self.controller.destroy)
exit_Btn.grid(row=1, column=1, padx=30, pady=5)
def starting_Program(self):
pass
class selectionPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamSelect()
def teamSelect(self):
heading = Label(self, text="Become a member of a Team",
font=('Arial', 25))
heading.grid(row=0, column=0, columnspan=2, padx=200, pady=40)
teams = Button(self, text="Teams", font="Arial 24", width=15,
command=lambda: self.controller.show_frame(TeamsPage))
teams.grid(row=1, column=0, padx=270, pady=5)
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.userEntry()
def userEntry(self):
headingTest = Label(self, text="Enter your Username:", font="Arial 20")
headingTest.grid(row=0, column=0, pady=0)
usernameEnter = Entry(self, width=40)
usernameEnter.grid(row=0, column=1, padx=2, pady=10)
UserName = StringVar(self)
UserName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15)
teamSelection = OptionMenu(self, UserName, "Team1", "Team2", "Team3", "Team 4") # How to link those variations to team list? For example: Team 1 = team1Members?
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command=()) # Command to Save username in teamXMembers list. Depends on the user selection
confirmBtn.config(height=4, width=12)
confirmBtn.grid(row=2, column=2, sticky=E, padx=65, pady=300)
if __name__ == '__main__':
app = CollegeApp()
app.geometry("800x500")
app.title('Points Counter')
app.mainloop()
Screenshot of this window:
There are few ways that could achieve this. The First would be to create a list of teams and unpack them using * in optionMenu then use if else condition to check which list to append to.
Here is a demo
class TeamsPage(ttk.Frame):
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamList = ["Team1", "Team2", "Team3", "Team 4"]
self.userEntry()
def userEntry(self):
...
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=2, pady=10)
self.userName = StringVar(self)
self.userName.set("Team1")
teamSelection = OptionMenu(self, self.userName, *self.teamList)
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command= self.updateTeamList) # Command to Save username in teamXMembers list. Depends on the user selection
...
def updateTeamList(self):
if self.userName.get() == self.teamList[0]:
team1Members.append(self.usernameEnter.get())
elif self.userName.get() == self.teamList[1]:
team2Members.append(self.usernameEnter.get())
...
but a better way would be to create a dictionary. something as shown
def __init__(self, parent, controller):
self.controller = controller
ttk.Frame.__init__(self, parent)
self.teamList = {"Team1": team1Members , "Team2": team2Members,
"Team3":team3Members, "Team 4": team4Members}
self.userEntry()
def userEntry(self):
...
self.usernameEnter = Entry(self, width=40)
self.usernameEnter.grid(row=0, column=1, padx=2, pady=10)
self.userName = StringVar(self)
self.userName.set("Team1")
AdditionalText = Label(self, text="Please select a team:", font="Arial 18")
AdditionalText.grid(row=1, column=0, sticky=W, pady=15)
teamSelection = OptionMenu(self, self.userName, *self.teamList.keys())
teamSelection.grid(row=1, column=1, sticky=W)
confirmBtn = Button(self, text="Submit", font="Arial 16",
command= self.updateTeamList) # Command to Save username in teamXMembers list. Depends on the user selection
...
def updateTeamList(self):
self.teamList[self.userName.get()].append(self.usernameEnter.get())
Hi Guys I have Problem after add background in my project, I don't see anything but after resize I see background: I don't want to use ttk in my object.
This is my code:
from tkinter import (Button, Label, Frame)
class HomeFrame(Frame): # Inherit Frame class
"""Application main interface"""
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.root = parent # Define internal variable root
self.root.configure(background='green')
self.home_page()
def home_page(self):
"""Load control"""
Label(self, text="First name").grid(row=0, column=0, padx=20, pady=20)
Full_name = Button(self, text="Get Full name")
Full_name.grid(row=0, column=1, columnspan=2, padx=20, pady=20)
Label(self, text="Last name").grid(row=1, column=0, padx=20, pady=20)
hello = Button(self, text="hello")
hello.grid(row=3, column=2, columnspan=2, padx=20, pady=20)
This is Result:
Interface without resize
After Resize:
Interface After Resize
from tkinter import (Button, Label, Frame)
class HomeFrame(Frame): # Inherit Frame class
"""Application main interface"""
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.root = parent # Define internal variable root
self.root.configure(background='green')
self.config(background='green')
self.home_page()
def home_page(self):
"""Load control"""
Label(self, text="First name").grid(row=0, column=0, padx=20, pady=20)
Full_name = Button(self, text="Get Full name")
Full_name.grid(row=0, column=1, columnspan=2, padx=20, pady=20)
Label(self, text="Last name").grid(row=1, column=0, padx=20, pady=20)
hello = Button(self, text="hello")
hello.grid(row=3, column=2, columnspan=2, padx=20, pady=20)
Small problem here, my code seem to be clean but the tkinter GUI doesn't appear ? Can seem to figure it out. The GUI / Code is for a report form type.
Thanks for your help in advance
from tkinter import *
class FicheDeSignalement(Frame):
def __init__(self):
Frame.__init__(self)
programme = Frame()
programme.pack(side="top", fill="both", expand=True)
programme.grid_rowconfigure(0, weight=5)
programme.grid_columnconfigure(0, weight=5)
self.pages = {}
for onePage in (StartProgram, InformationsPage):
start_page = onePage(programme, self)
self.pages[onePage] = start_page
start_page.grid(row=0, column=0, sticky="nsew")
self.show_pages(StartProgram)
def show_pages(self, cont):
see_start_page = self.pages[cont]
see_start_page.tkraise()
class StartProgram(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent, controller)
label = Label(self, text="Fiche de Signalement", font=LARGE_FONT)
label.pack(padx=10, pady=10)
start_button = Button(self, text="Commencer", command=lambda: controller.see_page(InformationsPage))
start_button.pack()
class InformationsPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent, controller)
label = Label(self, text="Informations sur le suspect", font=LARGE_FONT)
label.pack(side="top", fill="both", expand=True, padx=10, pady=10)
person_suspected = Label(self, text="Prenom")
person_suspected.grid(row=0, column=0, padx=10, pady=10)
first_name = Entry(self)
first_name.grid(row=0, column=1, padx=10, pady=10)
person_suspected_2 = Label(self, text="Nom")
person_suspected_2.grid(row=0, column=2, padx=10, pady=10)
last_name = Entry(self)
last_name.grid(row=0, column=3, padx=10, pady=10)
person_height = Label(self, text="Grandeur")
person_height.grid(row=1, column=0, padx=10, pady=10)
size_height = Entry(self)
size_height.grid(row=1, column=1, padx=10, pady=10)
person_weight = Label(self, text="Poids")
person_weight.grid(row=1, column=2, padx=10, pady=10)
size_weight = Entry(self)
size_weight.grid(row=1, column=3, padx=10, pady=10)
app = FicheDeSignalement()
app.mainloop()
In addition to indentation errors and missing import statements and missing definition of LARGE_FONT, you have this problem:
label = Label(self, text="Informations sur le suspect")
label.pack(side="top", fill="both", expand=True, padx=10, pady=10)
person_suspected = Label(self, text="Prenom")
person_suspected.grid(row=0, column=0, padx=10, pady=10)
Both label and person_suspected share the same parent (self), but one uses pack and one uses grid. You can't use both of them with widgets that share a common parent. You must use only grid or only pack.
the following code has an error where the "add task" button will add an empty input into the listbox by creating spaces between 2 tasks. Is there a way by coding this where it can't happen? I want the list in the listbox to be sequential where each task appears one after another. I don't understand why this happens. Is it a part of python? Thanks again.
import tkinter as tk
def main():
root = tk.Tk()
root.geometry("350x450")
root.title("basic window")
root.config(background="azure")
app = Application (root)
root.mainloop()
class Application(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="yellow", bd=2, relief=tk.RIDGE)
self.parent = parent
self.initUI()
def initUI(self):
self.pack(fill="both", expand=1)
#widget layout
self.listbox = tk.Listbox(self, bd=2, relief=tk.SUNKEN, height="15")
self.listbox.grid(row=0, column=0, sticky="w", padx=5, pady=5)
self.entry=tk.Entry(self, width=19)
self.entry.grid(row=1, stick="w", padx=5)
self.button1=tk.Button(self, text="add task", command=self.update)
self.button1.grid(row=1, column=1, sticky="w", padx=5)
self.label=tk.Label(self, text="stats", bg="yellow")
self.label.grid(row=0, column=1, sticky="n")
#programing
def update(self):
self.listbox.insert("end", self.entry.get())
self.entry.delete(0, "end")
if __name__ == '__main__':
main()
in update(self), you need to test if self.entry.get() contains an empty string; if it does, skip the update.
import tkinter as tk
class Application(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent, bg="yellow", bd=2, relief=tk.RIDGE)
self.parent = parent
self.initUI()
def initUI(self):
self.pack(fill="both", expand=1)
#widget layout
self.listbox = tk.Listbox(self, bd=2, relief=tk.SUNKEN, height="15")
self.listbox.grid(row=0, column=0, sticky="w", padx=5, pady=5)
self.entry=tk.Entry(self, width=19)
self.entry.grid(row=1, stick="w", padx=5)
self.button1=tk.Button(self, text="add task", command=self.update)
self.button1.grid(row=1, column=1, sticky="w", padx=5)
self.label=tk.Label(self, text="stats", bg="yellow")
self.label.grid(row=0, column=1, sticky="n")
#programing
def update(self):
if self.entry.get() != '':
self.listbox.insert("end", self.entry.get())
self.entry.delete(0, "end")
def main():
root = tk.Tk()
root.geometry("350x450")
root.title("basic window")
root.config(background="azure")
app = Application (root)
root.mainloop()
if __name__ == '__main__':
main()
def update(self):
if not self.entry.get()== "": #.get gets the value thgat the entry contains
self.listbox.insert("end", self.entry.get())
self.entry.delete(0, "end")
Also on a side note i would suggest using better names for example instead of self.entry use something self.intput_txt, when i make object i tend to use _txt or _lbl ectra as it makes it easier to see at a glance what type of object it is
I need to return all variables from all tabs by clicking on ok button.
I have two tabs. What I want is that when I enter some value in 2nd tab, it should automatically appear in first tab in 'height' entry.
Then if I click 'ok' in first tab, it should return all variables(from first tab and 2nd tab) to my 'main' program for further use.
Thanks
from tkinter import *
from tkinter import ttk
class App1(ttk.Frame):
def createWidgets(self):
#text variables
self.i_height = StringVar()
self.i_weight = StringVar()
self.o_bmi = StringVar()
#labels
self.label1 = ttk.Label(self, text="Enter your weight:").grid(row=0, column=0, sticky=W)
self.label2 = ttk.Label(self, text="Enter your height:").grid(row=1, column=0, sticky=W)
self.label3 = ttk.Label(self, text="Your BMI is:").grid(row=2, column=0, sticky=W)
#text boxes
self.textbox1 = ttk.Entry(self, textvariable=self.i_weight).grid(row=0, column=1, sticky=E)
self.textbox2 = ttk.Entry(self, textvariable=self.i_height).grid(row=1, column=1, sticky=E)
self.textbox3 = ttk.Entry(self, textvariable=self.o_bmi).grid(row=2, column=1, sticky=E)
#buttons
self.button1 = ttk.Button(self, text="Cancel/Quit", command=self.quit).grid(row=3, column=1, sticky=E)
self.button1 = ttk.Button(self, text="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)
def calculateBmi(self):
try:
self.weight = float(self.i_weight.get())
self.height = float(self.i_height.get())
self.bmi = self.weight / self.height ** 2.0
self.o_bmi.set(self.bmi)
except ValueError:
messagebox.showinfo("Error", "You can only use numbers.")
finally:
self.i_weight.set("")
self.i_height.set("")
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.createWidgets()
class App2(ttk.Frame):
def create_widgets(self):
"""Create the widgets for the GUI"""
#1 textbox (stringvar)
self.entry= StringVar()
self.textBox1= ttk.Entry(self, textvariable=self.entry).grid(row=0, column=1)
#5 labels (3 static, 1 stringvar)
self.displayLabel1 = ttk.Label(self, text="feet").grid(row=0, column=2, sticky=W)
self.displayLabel2 = ttk.Label(self, text="is equivalent to:").grid(row=1, column=0)
self.result= StringVar()
self.displayLabel3 = ttk.Label(self, textvariable=self.result).grid(row=1, column=1)
self.displayLabel4 = ttk.Label(self, text="meters").grid(row=1, column=2, sticky=W)
#2 buttons
self.quitButton = ttk.Button(self, text="Quit", command=self.quit).grid(row=2, column=1, sticky=(S,E))
self.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))
def convert_feet_to_meters(self):
"""Converts feet to meters, uses string vars and converts them to floats"""
self.measurement = float(self.entry.get())
self.meters = self.measurement * 0.3048
self.result.set(self.meters)
def __init__(self, master=None):
ttk.Frame.__init__(self, master)
self.grid()
self.create_widgets()
def button1_click():
root = Tk()
app = App1(master=root)
app.mainloop()
def button2_click():
root = Tk()
app = App2(master=root)
app.mainloop()
def main():
#Setup Tk()
window = Tk()
#Setup the notebook (tabs)
notebook = ttk.Notebook(window)
frame1 = ttk.Frame(notebook)
frame2 = ttk.Frame(notebook)
notebook.add(frame1, text="BMI Calc")
notebook.add(frame2, text="Feet to Meters")
notebook.grid()
#Create tab frames
app1 = App1(master=frame1)
app1.grid()
app2 = App2(master=frame2)
app2.grid()
#Main loop
window.mainloop()
main()
You have some fundamental mistakes in your program -- you cannot have three mainloops running at the same. You should always only have exactly one instance of Tk, and call mainloop exactly once.
Regardless of that, the solution is that you need to create a method or public variable in the app, and then your button callback needs to be able to call that method or access that variable.
For example, you would do it like this:
def callback():
value1 = app1.getValue()
value2 = app2.getValue()
...