Cannot create Entry widget with tkinter - python

I'm having some trouble creating an entry widget with tkinter. I've imported the necessary modules and have already created several buttons and check boxes. However I cannot figure out how to properly initialize the Entry. Here is my relevant code:
# Necessary Modules.------------------------------------------------------------
import win32com.client as win32
import re
from tkinter import *
from tkinter.filedialog import askopenfilename
import tkinter.messagebox
# Class for selecting the file.-------------------------------------------------
class FilenameClass():
def __init__(self):
self.location = 'User Import.txt'
def getFile(self, identity):
self.file_opt = options = {}
options['defaultextension'] = '.txt'
options['filetypes'] = [('Text Document (.txt)', '.txt'),
('all files', '.*')]
self.filename = askopenfilename(**self.file_opt)
if self.filename:
if 'User Import' in identity:
self.location = self.filename
app.get_txt_File['bg'] = '#0d0'
user_file = open(self.filename, 'r')
user_total = user_file.read()
remove_lines = user_total.splitlines()
for user in remove_lines:
regex_tab = re.compile('\\t')
user_info = regex_tab.split(user)
app.users.append(user_info)
else:
app.loadButton['bg'] = '#e10'
# Main Class.-------------------------------------------------------------------
class Application(Frame, Tk):
def __init__(self, master=None):
Frame.__init__(self, master)
self.users = []
self.fileOBJtxt = FilenameClass()
self.createWidgets()
def createWidgets(self):
# Define the default values for the options for the buttons
# Grid layout options
self.rowconfigure(0, minsize=5)
self.width = 54
self.grid(padx=5)
self.loadButton_gopt = {'row':1,'column':1,'padx': 2, 'pady': 5}
self.loadButton_wopt = {'width': round(self.width),'bg':'#e10'}
self.loadButton()
self.trainingCheckBox()
self.signatureInput()
def loadButton(self):
'''Button that calls the filename class which allows the user to select
the text file they wish to use.'''
self.get_txt_File = Button(self, text="Load User List", \
command=lambda: self.fileOBJtxt.getFile('User Import'))
for key, value in self.loadButton_wopt.items():
self.get_txt_File[key] = value
self.get_txt_File.grid(**self.loadButton_gopt)
def trainingCheckBox(self):
self.training_var = IntVar()
self.training = Checkbutton(text="Include training video?", \
variable=self.training_var).grid(row=2, sticky=W)
def signatureInput(self):
Label(text="Signature Name").grid(row=4, sticky=W)
entry = Entry(bg='#fff', width=50)
entry.grid(row=4, column=1, columnspan=4)
# Initialization parameters.----------------------------------------------------
if __name__ == '__main__':
app = Application()
app.master.title('User Notification Tool')
app.master.geometry('405x550+100+100')
app.master.resizable(width=False, height=False)
app.mainloop()
I'm not seeing any tracebacks, but I can't seem to get my Entry box to show up. What am I doing wrong?
EDIT: added entire code.

The problem with your entry field is you have not told it what frame/window to be placed in.
Change:
entry = Entry(bg='#fff', width=50)
To:
entry = Entry(self, bg='#fff', width=50)
Make sure you always provide the window/frame that a widget is going to be placed in as the first argument. In this case it is self as self refers to a frame.
Keep in mind that your program will not be able to get() the string inside of your entry field because you have not defined it as a class attribute. So most likely you will need to change
This:
entry = Entry(bg='#fff', width=50)
entry.grid(row=4, column=1, columnspan=4)
To This:
self.entry = Entry(self, bg='#fff', width=50)
self.entry.grid(row=4, column=1, columnspan=4)
This change will be necessary in order for the rest of your application to be able to read or write to the entry widget.

Change
entry = Entry(bg='#fff', width=50)
to
entry = tk.Entry(bg='#fff', width=50)

Related

Change main class label's text from different class using toplevel in tkinter

Just picked up tkinter recently
I have a program where when a user click a [...] button, it will display a toplevel window containing a calendar and [OK] button inside it.
When the user click the [OK] button, I want it to change [startDate] variable, and [labelStartDate] label in the main window.
I need the [startDate] variable for my next data process. and [labelStartDate] label is to show user that the date is changed.
How to achieve that?
I tried to use command=lambda or stringvar, but honestly I am kinda lost trying to apply it to my program.
from datetime import date
from textwrap import fill
import tkinter as tk
from tkinter import ttk
from tkinter import Toplevel
from tkinter import font
from tkcalendar import Calendar
from turtle import color, width
# Define the GUI
class App(tk.Tk):
def __init__(self):
super().__init__()
# root window
self.title('Main Window')
self.geometry('620x570')
global startDate #variable that I want to use for later data processing
startDate = date.today().strftime("%Y/%m/%d/")
#DATE MENU FRAME
DateMenuBar = ttk.LabelFrame(self.master, borderwidth = 1, text='Setting')
subFrame2 = tk.Frame(DateMenuBar, borderwidth = 1, relief = tk.FLAT, pady=0, padx=0)
#SUB FRAME 2
labelStart = tk.Label(subFrame2, text='Start',font=('meiryoui', 15))
labelStartDate = tk.Label(subFrame2, text=startDate,font=('meiryoui', 15))
btnOpenCalendar1 = tk.Button(subFrame2, height=1, background='#eeeeee', text='...', font=('meiryoui', 8), command=self.changeStartDate)
labelStart.pack(side = tk.LEFT, ipadx=10)
labelStartDate.pack(side = tk.LEFT, padx=(30,10))
btnOpenCalendar1.pack(side = tk.LEFT)
subFrame2.pack(fill = tk.X,padx=0, pady=10)
DateMenuBar.pack(fill = tk.X,padx=20, ipadx=20, ipady=20)
def changeStartDate(self):
window = Window(self)
window.grab_set()
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title("Pick Date")
self.geometry("250x250")
def selectStartDate():
startDate = cal.get_date()
#I got stuck here, trying to figure out how to change the labelStartDate's text
cal = Calendar(self, selectmode = 'day')
cal.pack(padx=20, pady=10)
frame = tk.Frame(self, borderwidth = 1, relief = tk.FLAT, pady=10, padx=20)
btnOK = tk.Button(frame, height=2,width=8, background='#eeeeee', text='OK', font=('meiryoui', 9),command=selectStartDate)
btnCancel = tk.Button(frame, height=2,width=8, background='#eeeeee', text='Cancel', font=('meiryoui', 9))
btnOK.pack(side = tk.RIGHT, padx=(10,0))
btnCancel.pack(side = tk.RIGHT)
frame.pack(fill = tk.X)
if __name__ == "__main__":
app = App()
app.mainloop()
Edit Note:
I added the missing code to my program so that it can be run by others :)
You can first use tkinter.StringVar() and set the label textvariable to the same, inorder to be able to modify the label's text.
self.labelStartDateVar = tk.StringVar() # Initalizing the text variable
self.labelStartDateVar.set(startDateData.start_date) # Setting initial value of the textvariable.
# Added textvariable as labelStartDateVar
self.labelStartDate = tk.Label(subFrame2, textvariable = labelStartDateVar, font = ('meiryoui', 15))
Further, using some knowledge from this post(of Observer Pattern), it is possible to call a function when a change in the startDate is detected. We do so by defining a new class and using a startDateData object as the global object, and to get the value of startDate itself, we simply need to access it's start_date property startDateData.start_date to set it the same property needs to be set like so -:
startDateData.start_date = cal.get_date()
The full code will look something like this -:
class startDate(object):
def __init__(self):
# Setting the default value as in the OP.
self._start_date = date.today().strftime("%Y年 %m月 %d日")
self._observers = []
return
#property
def start_date(self):
return self._start_date
#start_date.setter
def start_date(self, value):
self._start_date = value
for callback in self._observers:
print('announcing change')
callback(self._start_date)
return
def bind_to(self, callback):
print('bound')
self._observers.append(callback)
startDateData = startDate() # global startDateData object.
# Define the GUI
class App(tk.Tk):
def __init__(self):
super().__init__()
# root window
self.title('Main Window')
self.geometry('620x570')
global startDateData #variable that I want to use for later data processing
###
self.labelStartDateVar = tk.StringVar()
self.labelStartDateVar.set(startDateData.start_date)
startDateData.bind_to(self.updateStartDate) # Binding the updateStartDate function to be called whenever value changes.
###
#SUB FRAME 2
self.labelStart = tk.Label(subFrame2, text='開始',font=('meiryoui', 15))
# Added textvariable as labelStartDateVar
self.labelStartDate = tk.Label(subFrame2, textvariable = self.labelStartDateVar, font = ('meiryoui', 15))
self.btnOpenCalendar1 = tk.Button(subFrame2, height=1, background='#eeeeee', text='...', font=('meiryoui', 8), command=self.changeStartDate)
self.labelStart.pack(side = tk.LEFT, ipadx=10)
self.labelStartDate.pack(side = tk.LEFT, padx=(30,10))
self.btnOpenCalendar1.pack(side = tk.LEFT)
subFrame2.pack(fill = tk.X,padx=0, pady=10)
def updateStartDate(self, startDate) :
self.labelStartDateVar.set(startDate)
return
class Window(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.title("Pick Date")
self.geometry("250x250")
# Globally fetch the startDateData object.
global startDateData
def selectStartDate():
# All binded callbacks will be called, when the value is changed here.
startDateData.start_date = cal.get_date()
cal = Calendar(self, selectmode = 'day')
cal.pack(padx=20, pady=10)
frame = tk.Frame(self, borderwidth = 1, relief = tk.FLAT, pady=10, padx=20)
btnOK = tk.Button(frame, height=2,width=8, background='#eeeeee', text='OK', font=('meiryoui', 9),command=selectStartDate)
btnCancel = tk.Button(frame, height=2,width=8, background='#eeeeee', text='Cancel', font=('meiryoui', 9))
btnOK.pack(side = tk.RIGHT, padx=(10,0))
btnCancel.pack(side = tk.RIGHT)
frame.pack(fill = tk.X)
NOTE: As the code provided in the OP, was not adequate enough to be able to test whether this solution works. Further, as the initial code provided seemed to be incomplete, the full code given in the answer at the end may also seem incomplete but still implements all the features present in the code given in the OP.
EDIT: The previous placement of the line startDateData = startDate() was wrong as it was trying to construct an object of a class before it is defined, now the line has been shifted below the class definition of startDate.
EDIT 2: Fixed some of the typos, as mentioned in the comments by #Mario Ariyanto.

How to retain the value of an entry field acquired in a popup toplevel window in tkinter?

I cannot get my code to pass the pop up text entry to a global variable i am also attempting to set this global variable as the default text in the entry field in all future instances.
Pop up -> Enter Filepath -> accept&close -> Re-open shows last filepath present as default -> if changed new filepath entry becomes default in future.
import tkinter as tk
from tkinter import ttk
from tkinter import *
master = tk.Tk()
Var1 = StringVar()
Filepath_Var = None
def A_Connect():
root = Tk()
root.title("Entry Field")
def entry_field():
global Filepath_Var
Filepath_Var = Var1.get()
tk.Label(root, text="filepath: ").grid(row=0)
e1 = tk.Entry(root, textvariable=Var1)
tk.Label(root, text="Item Number: ").grid(row=1)
e2 = tk.Entry(root)
#e1.insert(0, r"C:\Users\zxy\ghj\iugf\Bea\something.xlsx")
e1.insert(0, Var1.get())
e1.grid(row=0, column=1)
e2.grid(row=1, column=1)
Button(root, text = 'Accept', command = entry_field).grid(row=3, column=1,
sticky=W, pady=4)
root.mainloop()
note = ttk.Notebook(master)
tab1 = tk.Frame(note)
canvas7 = Canvas(tab1, width=520, height=350)
canvas7.pack()
A_Button = tk.Button(tab1, text="A",
width=12, height=3,command=A_Connect, anchor = 'w')
A_Button_Window = canvas7.create_window(20, 120, anchor = 'sw',
window = A_Button)
note.add(tab1, text = " Main ")
note.pack()
master.mainloop()
As a follow up to your earlier question, I encapsulated an example of the (bare bones) desired behavior in two classes:
The main App consists of a button that launches an entry popup; upon filling the fields and accepting, the value in the entry is provided to the App, and the popup closed.
The value entered is stored by the App, and used to populate the entry field of the entry fields in successive popups.
You will probably want to add confirmations and verifications before changing the defaults, and closing the popup, but here, you have the basic skeleton to attach this to.
import tkinter as tk
class PopUpEntry(tk.Toplevel):
def __init__(self, master, default_value=None):
self.master = master
super().__init__(self.master)
if default_value is None:
self.default_entry = 'C:*****\somthing.xlsx'
else:
self.default_entry = default_value
self.title("Entry Field")
tk.Label(self, text="Filepath: ").pack()
self.e1 = tk.Entry(self)
self.e1.insert(0, self.default_entry)
self.e1.pack()
tk.Button(self, text = 'Accept', command=self.entry_field).pack()
def entry_field(self):
self.default_entry = self.e1.get()
self.master.provide_entry_value(self.default_entry)
self.destroy()
class App(tk.Tk):
def __init__(self):
super().__init__()
self.pop_entry = tk.Button(self, text='launch entry', command=self.launch_entry)
self.pop_entry.pack()
self.default_entry_value = None
self.mainloop()
def launch_entry(self):
PopUpEntry(self, self.default_entry_value)
def provide_entry_value(self, value):
self.default_entry_value = value
print(self.default_entry_value)
App()

Pass data frame through Tkinter classes

I am using Python 2.7 and Tkinter. I am almost new to Object Oriented programs. I have a long program with many Tkinter windows and at some point I ask the user to load an Excel file that I read with Pandas, and want to permanently use and update that value (of a data variable). The way that I am doing it now is with global variables but I know that it is dangerous, inefficient and not elegant at all.
Even though I could do controller.show_frame(framename) given the way my gui class is built, I ended up building some of the frames myself just so the data variable would update itself.
I read and tried some answers in Stack Overflow but may have implemented them wrong:
Tried creating a dictionary inside the gui class, something like self.app_data = {data=[],filename=""} and updating it from other windows, the thing here is that I think that the class gui is instanced only once and it kind of creates all of the other window classes so this did not work. Maybe I did something wrong there. (not shown on the code).
Tried to do something as what was suggested here but I could just not make it work.
Main frame is some sort of intermediate step that I need for other purposes; the following code is a simplification of my program.
I know this is an awful nightmare code! Thank you :)
import Tkinter as tk
import pandas as pd
import tkFileDialog
import tkMessageBox
global data, strat_columns, filename
data = pd.DataFrame([])
strat_columns = []
filename = ""
class gui(tk.Tk):
data = pd.DataFrame([])
filename = ""
def __init__(self):
tk.Tk.__init__(self)
container = tk.Frame(self)
container.pack(side="top",fill="both",expand=True)
self.frames = {}
for F in (main_frame, first_frame):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(main_frame)
def show_frame(self,sel_frame):
frame = self.frames[sel_frame]
frame.tkraise()
def get_page(self, page_class):
return self.frames[page_class]
class main_frame(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.parent = parent
self.controller = controller
button_new = tk.Button(self,
text="New window",
command=lambda: self.button_new_callback())
button_new.pack()
def button_new_callback(self,*args,**kwargs):
self.controller.show_frame(first_frame)
class first_frame(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.controller = controller
self.parent = parent
self.show_frame = controller.show_frame
statusText.set("Press Browse button and browse for file, then press the Go button")
label = tk.Label(self, text="Please load a file: ")
label.pack()
entry = tk.Entry(self, width=50)
entry.pack()
button_go = tk.Button(self,
text="Go",
command=lambda: self.button_go_callback(entry,statusText,message))
button_browse = tk.Button(self,
text="Browse",
command=lambda: self.button_browse_callback(entry))
button_go.pack()
button_browse.pack()
message = tk.Label(self, textvariable=statusText)
message.pack()
def button_browse_callback(self,entry):
global filename
filename = tkFileDialog.askopenfilename()
entry.delete(0, tk.END)
entry.insert(0, filename)
def button_go_callback(self,entry,statusText,message):
global data
input_file = entry.get()
data = pd.read_excel(filename)
sf = second_frame(self.parent, self)
sf.grid(row=0, column=0, sticky="nsew")
sf.tkraise()
class second_frame(tk.Frame):
pass
if __name__ == "__main__":
my_gui = gui()
my_gui.mainloop()
my_gui.title("TEST")
There are a few things that are causing issues with your program from running properly.
The first thing I noticed is the use of global variables. This can be avoided with the use of class attributes.
For the 2 variables you have just below the line class gui(tk.Tk): you need to move them to the __init__ section so those variables can be instantiated. Also you need to make them into class attributes so other methods or even other classes can interact with them. We can do this by adding the self. prefix to the variable names.
Something like the below:
self.data = pd.DataFrame([])
self.filename = ""
To access the methods/attributes of the gui class you need to pass the object of the gui class to the other classes working with it.
statusText in your code is not defined so set() wont work here. Just add self.statusText as a class attribute.
Some of your widgets do not need to be assigned to a variable name as no editing is being done to them. For example:
label = tk.Label(self, text="Please load a file: ")
label.pack()
This can be simply changed to:
tk.Label(self, text="Please load a file: ").pack()
This will help reduce the amount of code you are writing and keep the name space cleaner.
There are a few ways to correct all this but the easiest way is to move this code into one class. There is not a good reason with the code you have presented to have several frames separated from the main gui class.
The below code is a rewritten version of your code using one class to accomplish what appears to be the task your code is trying to accomplish and reducing the amount of code needed by around 30+ lines. I am sure it can be refined further but this example should be helpful.
import Tkinter as tk
import pandas as pd
import tkFileDialog
class gui(tk.Frame):
def __init__(self, master, *args, **kwargs):
tk.Frame.__init__(self, master, *args, **kwargs)
self.master = master
self.data = pd.DataFrame([])
self.filename = ""
self.strat_columns = []
self.main_frame()
self.first_frame()
self.mainframe.tkraise()
def get_page(self, page_class):
return self.frames[page_class]
def main_frame(self):
self.mainframe = tk.Frame(self.master)
self.mainframe.grid(row=0, column=0, sticky="nsew")
tk.Button(self.mainframe, text="New window",
command=lambda: self.firstframe.tkraise()).pack()
def first_frame(self):
self.firstframe = tk.Frame(self.master)
self.firstframe.grid(row=0, column=0, sticky="nsew")
self.statusText = tk.StringVar()
self.statusText.set("Press Browse button and browse for file, then press the Go button")
label = tk.Label(self.firstframe, text="Please load a file: ").pack()
self.first_frame_entry = tk.Entry(self.firstframe, width=50)
self.first_frame_entry.pack()
tk.Button(self.firstframe, text="Go", command=self.button_go_callback).pack()
tk.Button(self.firstframe, text="Browse", command=self.button_browse_callback).pack()
self.message = tk.Label(self.firstframe, textvariable=self.statusText)
self.message.pack()
def button_browse_callback(self):
self.filename = tkFileDialog.askopenfilename()
self.first_frame_entry.delete(0, tk.END)
self.first_frame_entry.insert(0, self.filename)
def button_go_callback(self):
self.data = pd.read_excel(self.filename)
if __name__ == "__main__":
root = tk.Tk()
root.title("TEST")
my_gui = gui(root)
root.mainloop()
in my opinion your are tying too much the data and the GUI. What if in the future you want to display something else? I would use a more generic approach: I would a create a DataProvider class that would read and return the data for you:
Data Provider
import pandas as pd
class DataProvider(object):
def __init__(self):
self._excel = {}
self._binary = {}
def readExcel(self, filename):
self._excel[filename] = pd.read_excel(filename)
def excel(self):
return self._excel
def readBinary(self, filename):
self._binary[filename] = open(filename,"rb").read()
def binary(self):
return self._binary
Using this class you can obtain the data that you can present in your GUI:
gui.py
from Tkinter import *
from DataProvider import *
import binascii
#example data
dp = DataProvider()
dp.readExcel("file.xlsx")
dp.readBinary("img.png")
root = Tk()
frame = Frame(root)
frame.pack()
bottomframe = Frame(root)
bottomframe.pack( side = BOTTOM )
w = Label(bottomframe, text=dp.excel()["file.xlsx"])
w.pack()
w = Label(bottomframe, text=binascii.hexlify(dp.binary()["img.png"][:5]))
w.pack()
root.mainloop()
If all works well you should have a small GUI showing the content of the Excel file and the first few bytes of the image.
Let me know if all works fine or if you need more info.
Thanks

Python - Tkinter. Why doesn't my tkinter entry connect to the last variable in the list?

I have a class port which has a name field.
I then have a main window which opens up a form for entering new ports. This form has a button on the first line which when pressed adds a new port to the frame where you can enter the name of the new port etc.
The Entry box's textvariable I've connected to the last port's name in the port-list, however it will not print the correct names when I press the Print button.
If changing the line
MAIN_gui = MAIN_GUI(root)
to
MAIN_interface_pkg(root)
Then it works as I want.
It is the first attempt for me with Python and Tkinter so please have some oversight with bad coding...
#!/usr/bin/env python
import Tkinter as tk
MAIN_VERSION='3.6e'
class Port:
def __init__(self, name, mode, direction):
self.name = tk.StringVar()
self.name.set(name)
self.mode= tk.StringVar()
self.mode.set(mode)
self.direction= tk.StringVar()
self.direction.set(direction)
def quit():
root.destroy()
class MAIN_GUI(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self,parent)
frame = tk.Frame(parent)
frame.pack(expand='0', fill='x')
frame_buttons = tk.Frame(frame, borderwidth='1', relief='groove')
frame_buttons.pack(side=tk.TOP)
frame_quit = tk.Frame(frame, borderwidth='1', relief='groove')
frame_quit.pack(side=tk.TOP)
################
label = tk.Label(frame, text="MAIN Gui version "+MAIN_VERSION)
label.pack(side=tk.TOP)
################
quit_button = tk.Button(frame_quit, text="QUIT", fg="red", command=root.quit)
quit_button.pack(side=tk.TOP)
intf_button = tk.Button(frame_buttons, text="Create Interface Package", command=self.intf_button_action)
intf_button.pack(side=tk.LEFT)
def intf_button_action(self):
global MAIN_interface_pkg_window
if MAIN_interface_pkg_window is None:
MAIN_interface_pkg_window = tk.Tk()
MAIN_interface_pkg = MAIN_INTERFACE_PKG(MAIN_interface_pkg_window)
else:
MAIN_interface_pkg_window.update()
MAIN_interface_pkg_window.deiconify()
class MAIN_INTERFACE_PKG(tk.Frame):
def __init__(self, parent):
self.ports = []
self.main_frame = tk.Frame(parent)
self.main_frame.pack()
self.frame_button = tk.Frame(self.main_frame)
self.frame_button.pack(side=tk.BOTTOM)
self.print_button = tk.Button(self.frame_button, text="Print", fg="blue", command=self._dbg)
self.print_button.pack(side=tk.TOP)
self.frame_three = tk.Frame(self.main_frame, borderwidth=3, relief="groove")
self.frame_three.pack(side=tk.TOP)
self._addport(self.frame_three)
def _dbg(self):
for port in self.ports:
print("DBG:" + str(port.name.get()) + " - " + port.mode.get())
def _addport(self,frame):
tmp_port = Port("name", "Two", "Input")
self.ports.append(tmp_port)
self.frame_addport = tk.Frame(frame)
self.frame_addport.pack(side=tk.TOP)
if (len(self.ports) == 1):
self.button_portname = tk.Button(self.frame_addport, text = "[+] Port Name:", width=12, command=lambda:self._addport(frame))
self.button_portname.pack(side=tk.LEFT)
else:
self.label_portname = tk.Label(self.frame_addport, text = " Port Name:", width=14)
self.label_portname.pack(side=tk.LEFT, padx=4)
self.e = tk.Entry(self.frame_addport, textvariable=self.ports[-1].name)
self.e.pack(side=tk.LEFT)
for text in ["One", "Two", "Three", "Four"]:
self.b = tk.Radiobutton(self.frame_addport, text=text,
variable=self.ports[-1].mode, value=text)
self.b.pack(side=tk.LEFT)
root=tk.Tk()
MAIN_interface_pkg_window = tk.Tk()
MAIN_interface_pkg = MAIN_INTERFACE_PKG(MAIN_interface_pkg_window)
MAIN_interface_pkg_window.withdraw()
MAIN_gui= MAIN_GUI(root)
root.mainloop()
You are calling Tk() twice in your code. This results in two entirely separate Tk instances running, each with its own set of variables. I'm not sure of the exact rules here, but evidently your StringVar()s are being created in a different instance than they are being used.
To create more than one window in a Tkinter application, you have to use Toplevel() for all but one of them.

Python widgets and button

I'm trying to add a "Done" button to my program that will print the content of both Entry widgets to a new box. I can get the button to appear, but I can't get the information to show up in a new box. What am I doing wrong?
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.grid()
self._name = StringVar()
self._name.set("Enter name here")
self._age = IntVar()
self._age.set("Enter age here")
top = self.winfo_toplevel() # find top-level window
top.title("Entry Example")
self._createWidgets()
self._button = Button(self,
text = "Done")
self._button.grid(row = 1, column = 0, columnspan = 2)
def _createWidgets(self):
textEntry = Entry(self, takefocus=1,
textvariable = self._name, width = 40)
textEntry.grid(row=0, sticky=E+W)
ageEntry = Entry(self, takefocus=1,
textvariable = self._age, width = 20)
ageEntry.grid(row=1, sticky=W)
def _widget(self):
tkMessageBox.showinfo
# end class Application
def main():
Application().mainloop()
You need to assign an action to your button using command: option.
To get what is written in Entry you need to use get() method.
showinfo you need two arguments, one is the title, the other one is what is going to be shown.
Also you need to import tkMessageBox.
Here is a working example.
import Tkinter as tk
import tkMessageBox
class Example(tk.Frame):
def __init__(self,root):
tk.Frame.__init__(self, root)
self.txt = tk.Entry(root)
self.age = tk.Entry(root)
self.btn = tk.Button(root, text="Done", command=self.message)
self.txt.pack()
self.age.pack()
self.btn.pack()
def message(self):
ent1 = self.txt.get()
ent2 = self.age.get()
tkMessageBox.showinfo("Title","Name: %s \nAge: %s" %(ent1,ent2))
if __name__=="__main__":
root = tk.Tk()
root.title("Example")
example = Example(root)
example.mainloop()

Categories

Resources