Use data from combobox from one class inside another class - python-3.x

I am trying to make a programm where in one frame (window) I have a combobox, then after selecting the combobox value I want it to print a message based on it's value on another window (class), but it says 'int' object has no attribute 'comboBoxDiamUnitString'.
As you will see, I first create the main App, then open up the start page where the combobox is, I select it's value and after some other procees I didn't put in the code as it runs ok I get to the next window, but then I can't use the combobox value in this new class I am in...
What am I missing? Thanks for your help in advance.
class App(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
MainMenu(self)
#Setup Frame
container = Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, context):
frame = self.frames[context]
frame.tkraise()
class StartPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
def confirmar():
if (self.jobStep >= 0):
respuesta = messagebox.askquestion( self.comboBoxDiamUnitString.get())
if respuesta == "yes":
respuestaInicio = messagebox.askquestion('Puesta en Marcha', 'Iniciar máquina')
if respuestaInicio == "yes":
messagebox.showinfo("Inicio", "Iniciando máquina")
controller.show_frame(PageOne)
self.comboBoxDiamUnitString = tkinter.StringVar()
self.comboBoxDiametro = ttk.Combobox(self, state="readonly", width=5, values=["AWG", "mm"], justify="right", textvariable=self.comboBoxDiamUnitString)
class PageOne(Frame):
def __init__(self, parent, controller):
self.i = 10
GPIO.setmode(GPIO.BOARD)
GPIO.setup(13,GPIO.IN,pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(13, GPIO.FALLING, callback=self.interrupt, bouncetime=300)
def interrupt(self, controller):
if(controller.comboBoxMetroVueltaString.get() == "Vueltas"):
print("vueltas")
if(controller.comboBoxMetroVueltaString.get() == "Metros"):
print("metros")

Related

Python Tkinter: How reset a combobox label from selecting option in another combobox in a parent, controler, container model?

The code is correct (and very interesting indeed - From stackoverlflow, because facilitate working comboboxes in classes!). The code is a little long, but just to create the structure to make combobox work in this parent, controler, container model. On the other hand,comoboboxes are "burning my brains out". The hard part: I can reset the lower combobox clicking the button. But I need to reset it to 'I´m your friend' just choosing any option in upper combobox (without use of button). I've tried insert "self.combobox_HPFilter.set('I´m your friend')" in a function and insert this in the functions called "make_guess", unfortunately unsuccessfuly. I really appreciate any help.
# from Bryan Oakley and others from the "amazing" Stackoverflow
# https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter/7557028#7557028
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
from tkinter import ttk
class SampleApp(tk.Tk):
'''
All the code is working.The sole issue is: to reset second combobox text direct from options in upper combobox
'''
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def make_guess01(self):
print("I've got a cute friend")
def make_guess02(self):
print('Ned is correct')
def make_guess03(self):
print('Patrick')
def make_guess04(self):
print('Best Hommer friend')
def labels_reset(self):
self.combobox_HPFilter.set('I´m your friend')
#-------------------------first combobox start
def change_Montage_combobox(self, event): # this method goes inside def montage_Combo(self):
myvar = (self.comboboxMontages.get())
# lines 1 2 3 4 say that values(function_name) in montageDict are functions in StartPage
function_name = self.montagesDict[myvar] #1 returns the function(method) in montageDic(value of key:value pair)
# just for reference: print(function_name)--> montage_Original (dictionary montagesDict value)
an_object = StartPage(self, tk.Frame) # 2--> the page (class) where function is
class_method = getattr(StartPage, function_name) # 3 returns method and says the page of the method
result = class_method(an_object) # 4 result is the method right for use
def montage_Combo(self):
self.montage_selector = tk.StringVar()
self.comboboxMontages = ttk.Combobox(self, values=sorted(list(self.montagesDict.keys())),
justify="center", textvariable=self.montage_selector, state="readonly",
)
self.comboboxMontages.bind('<<ComboboxSelected>>', lambda event: self.change_Montage_combobox(event))
self.comboboxMontages.pack()
self.comboboxMontages.set('Who is my friend')
#-------------------------first combobox end
#-------------------------second combobox start
def highPassFilter_Change_combobox(self, event): # this method goes inside def montage_Combo(self):
myvar = (self.combobox_HPFilter.get())
function_name = self.highPassFilterDict[myvar] # 1
an_object = StartPage(self, tk.Frame) # 2
class_method = getattr(StartPage, function_name) # 3
highPassFilter_result = class_method(an_object) # 4
def highPassFilter_Combo(self):
self.highPassFilter_selector = tk.StringVar()
self.combobox_HPFilter = ttk.Combobox(self, values=sorted(list(self.highPassFilterDict.keys())),
justify="center", textvariable=self.highPassFilter_selector,
state="readonly")
self.combobox_HPFilter.bind('<<ComboboxSelected>>', lambda event: self.highPassFilter_Change_combobox(event))
self.combobox_HPFilter.pack()
self.combobox_HPFilter.set('I´m your friend')
#-------------------------second combobox end
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.montagesDict = {'SpongeBob': 'make_guess01',
'Hommer': 'make_guess02'
}
self.highPassFilterDict = {'Patrick': 'make_guess03',
'Ned Flanders': 'make_guess04',
}
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="how reset lower combobox clicking upper combobox?",
command=self.labels_reset)
button1.pack()
self.montage_Combo()
self.highPassFilter_Combo()
#class PageOne just to make code play
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Python is both challenging and exciting, it seems a zen Koan. After "lots of try an error" and frustration...comes the light.
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
from tkinter import ttk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def make_guess01(self):
print("I've got a cute friend")
def make_guess02(self):
print('Ned is correct')
def make_guess03(self):
print('Patrick')
def make_guess04(self):
print('Best Hommer friend')
def labels_reset(self):
self.combobox_HPFilter.set('I´m your friend')
#-------------------------first combobox start
def change_Montage_combobox(self, event): # this method goes inside def montage_Combo(self):
myvar = (self.comboboxMontages.get())
# lines 1 2 3 4 say that values(function_name) in montageDict are functions in StartPage
function_name = self.montagesDict[myvar] #1 returns the function(method) in montageDic(value of key:value pair)
# just for reference: print(function_name)--> montage_Original (dictionary montagesDict value)
an_object = StartPage(self, tk.Frame) # 2--> the page (class) where function is
class_method = getattr(StartPage, function_name) # 3 returns method and says the page of the method
result = class_method(an_object) # 4 result is the method right for use
#################################
# answer: #
#################################
if self.combobox_HPFilter != '':
self.labels_reset()
else:
pass
def montage_Combo(self):
self.montage_selector = tk.StringVar()
self.comboboxMontages = ttk.Combobox(self, values=sorted(list(self.montagesDict.keys())),
justify="center", textvariable=self.montage_selector, state="readonly",
)
self.comboboxMontages.bind('<<ComboboxSelected>>', lambda event: self.change_Montage_combobox(event))
self.comboboxMontages.pack()
self.comboboxMontages.set('Who is my friend')
#-------------------------first combobox end
#-------------------------second combobox start
def highPassFilter_Change_combobox(self, event): # this method goes inside def montage_Combo(self):
myvar = (self.combobox_HPFilter.get())
function_name = self.highPassFilterDict[myvar] # 1
an_object = StartPage(self, tk.Frame) # 2
class_method = getattr(StartPage, function_name) # 3
highPassFilter_result = class_method(an_object) # 4
def highPassFilter_Combo(self):
self.highPassFilter_selector = tk.StringVar()
self.combobox_HPFilter = ttk.Combobox(self, values=sorted(list(self.highPassFilterDict.keys())),
justify="center", textvariable=self.highPassFilter_selector,
state="readonly")
self.combobox_HPFilter.bind('<<ComboboxSelected>>', lambda event: self.highPassFilter_Change_combobox(event))
self.combobox_HPFilter.pack()
self.combobox_HPFilter.set('I´m your friend')
def all_ComboBox_labels_reset(self):
self.combobox_HPFilter.set('I´m your friend')
#-------------------------second combobox start
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.montagesDict = {'SpongeBob': 'make_guess01',
'Hommer': 'make_guess02'
}
self.highPassFilterDict = {'Patrick': 'make_guess03',
'Ned Flanders': 'make_guess04',
}
label = tk.Label(self, text="This is the start page")
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="how reset lower combobox clicking upper combobox?",
command=self.labels_reset)
button1.pack()
self.montage_Combo()
self.highPassFilter_Combo()
#class PageOne just to make code play
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1")
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I used method self.combobox_HPFilter != '': because in my code there are multiple comboboxes to be reseted. "If" because at beginnig of script they are empty.
Excuse me I dont get the (-1)in my question, it is a question. It was usefull to me a beginner and no one answered until I found the answer. Indulge me and be more proactive explaining it. Best.

Class destory issue

I have three classes. Main class that creates the container for the mainframe frame, mainframe class which is nothing but a frame with an enable/disable button and a kill button and an application exit button. The third is a class that has a loop.
The "main" creates the mainframe and the instance of the loop class. The loop class has a variable stating if it is running or not and has two functions, one that pauses and un-pauses the loop enable (pause is by spacebar) and the other to stop(stop is by escape). You can tell more by the code. If problem is I don't just want to stop the class, I want to delete the class all together. How do I do this based off my code?
`
from mycomm import commloop
class main(tk.Tk):
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (mainframe, otherframe):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("mainframe")
self.b = commloop(self)
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def deletecommloop(self):
del self.b
def get_page(self, page_class):
return self.frames[page_class]
class mainframe(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
self.amiset = False
#''''code to frame stuff
buttont1 = tk.Button(frame5, text="create comm loop",
command=self.setme)
buttont1.place(relx=0.444, rely=0.496, height=42, width=90)
buttontt1 = tk.Button(frame5, text="kill comm loop",
command=self.killcommloop)
buttontt1.place(relx=0.244, rely=0.496, height=42, width=90)
def setme(self):
self.amiset = not (self.amiset)
def killcommloop(self):
self.controller.deletecommloop()
class commloop():
def __init__(self, root):
self.running = False
self.aboutToQuit = False
self.root = root
self.someVar = 0
self.root.bind("<space>", self.switch)
self.root.bind("<Escape>", self.stop)
self.page= root.get_page("mainframe")
while not self.aboutToQuit:
try:
self.root.update() # always process new events
if self.running:
# do stuff
self.someVar += 1
print(self.someVar)
time.sleep(.1)
else: # If paused, don't do anything
time.sleep(.1)
except:
self.aboutToQuit=True #does this need to be here?
def switch(self, event):
if (self.page.amiset):
print(['Unpausing','Pausing'][self.running])
self.running = not (self.running)
def stop(self, event):
self.aboutToQuit = True
`
the loop code I found on the internet. The aboutToQuit only keeps it from looping. I want the kill button on the mainframe page to call the killcommloop in main (since that is what started the commloop), but I am getting the error:
File "C:/testloop/mainframe.py", line 101, in killcommloop
self.controller.deletecommloop()
File "C:/testloop/main.py", line 66, in deletecommloop
del self.b
AttributeError: b

Tkinter window does not update correctly when running

I'm trying to make a Tkinter window show updated data but it only pops up after 13 seconds with just the last value. I want it to pop up and change the values on screen. Mind you, the big goal of this code is to take data from a database (which updates every 3 seconds) and show the data onscreen, while running continuously, so if the answer could include some pointers on the "after" or "update" functions it would be greatly appreciated!
Here is what I have so far.
from tkinter import *
import time
class GUI(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
Tk.wm_title(self, "Main Window")
self.container = Frame(self)
self.container.pack(side=TOP, fill=BOTH, expand=TRUE)
self.container.grid_rowconfigure(0, weight=1)
self.container.grid_columnconfigure(0, weight=1)
self.frames = {}
self.frame = StartPage(self.container, self)
self.frames[StartPage] = self.frame
self.frame.grid(row=0, column=0, sticky=NSEW)
self.show_frame(StartPage)
def show_frame(self, controller):
frame = self.frames[controller]
frame.tkraise()
class StartPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.label = Label(self, text="Current ID:\n")
self.label.pack(padx=10, pady=10)
self.data_label = Label(self)
self.data_label.pack()
self.update_data()
def update_data(self):
var1 = StringVar()
for i in range(10):
var1.set(str(i))
self.data_label.config(text=str(i))
time.sleep(1)
main = GUI()
main.mainloop()
I can give you a partial answer. The reason you don't see any updates is that time.sleep() suspends the process and does not allow for tkinter to repaint the window.
You don't use the label textvariable correctly. Specify it in the label and the label will change as you change the textvariable.
You use both pack and grid at the same time which may cause problems.
I have not used after() in a class before so I don't know how to work it, but this example should give you some pointers. I'm keeping console printouts in the code so I can see what it does.
from tkinter import *
import time
class GUI(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
Tk.wm_title(self, "Main Window")
self.container = Frame(self)
self.container.pack(side=TOP, fill=BOTH, expand=TRUE)
self.frames = {}
self.frame = StartPage(self.container, self)
self.frames[StartPage] = self.frame
self.frame.pack(side=TOP, fill=BOTH, expand=TRUE)
self.show_frame(StartPage)
def show_frame(self, controller):
frame = self.frames[controller]
frame.tkraise()
frame.update_data()
print('Done')
class StartPage(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
self.parent = parent
self.label = Label(self, text="Current ID:\n")
self.label.pack(padx=10, pady=10)
self.var1 = StringVar()
self.data_label = Label(self, textvariable=self.var1)
self.data_label.pack()
self.update_idletasks() # Calls all pending idle tasks
def update_data(self):
if not self.var1.get(): self.var1.set('0')
iteration = int(self.var1.get())
print('iteration', iteration)
if iteration < 3:
iteration = iteration + 1
self.var1.set(str(iteration))
self.update_idletasks() # Calls all pending idle tasks
time.sleep(1)
self.update_data()
main = GUI()
main.mainloop()
You will have to research after() yourself as I can't help you there.

Dynamic frame content python3 tkinter

Ok so, I am building an Sqlite browser in python(3) tkinter
Here is the problem. If you look at my code
The code derived from: http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
License: http://creativecommons.org/licenses/by-sa/3.0/
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
from sqlite3 import *
import operator
file = 'chinook.db'
conn = connect(file)
c = conn.cursor()
c.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
tables = c.fetchall()
tmplist = []
for i in tables:
tmplist.append(i[0])
LARGE_FONT= ("Verdana", 12)
print("done",tables)
global tabnam
tabnam = ''
def asign(sigh): #ok, yeah it was late and i didnt care much about naming convention
tabnam = sigh
#this function is supposed to assign the value given to the variable
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
#wrapper function
class SeaofBTCapp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Sea of BTC Client")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne):
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()
print("done")
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = ttk.Label(self, text=file, font=LARGE_FONT)
label.pack(pady=10,padx=10)
for i in tmplist:
button = ttk.Button(self, text="Visit Page " + str(i),
command=lambda:controller.show_frame(PageOne))
button.pack()
print("done")
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = ttk.Label(self, text='values', font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Home",command=lambda: controller.show_frame(StartPage))
button1.pack()
try:
c.execute("select * from {y}".format(y=tabnam))
for i in c.fetchall():
label = ttk.Label(text=i[0], font=LARGE_FONT)
label.pack(pady=10,padx=20)
except Exception as e:
print(e) # the error message indicates that the string formating identifies tabnam as " "
print("done")
app = SeaofBTCapp()
print("done")
app.mainloop()
print("done")
I'm trying to iterate an sqlite query. MEANING: i made it so that for every table, tkinter creates a button. This works. Tkinter displays a button with the name of every table. Now I want this code to be able to display every value in that table when that button is clicked. I have made a wrapping function to show the frame and reassign the current value of tabnam, the variable that represents the table name clicked by the user ; When the button is clicked, I reassign the value of a global variable named tabnam . But before the the buttons are even made, python just goes ahead and executes the query (thats yet to be formatted because user hasnt clicked button) and throws me an error. How do i fix this?

NameError: name 'clear_message' is not defined

from Tkinter import *
import tkinter as tk # python3
TITLE_FONT = ("Helvetica", 18, "bold")
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# the container is where I stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (MainPage,StorageOrMotor,Storage,Motor):
page_name = F.__name__
frame = F(container, self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("MainPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class MainPage(tk.Frame):
global user_key
global psw_key
user_key=""
psw_key=""
#Here is the defined for clear_message `def`
def clear_message():
user_key.delete(0, 'END')
psw_key.delete(0, 'END')
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
Username = tk.Label(self, text="Username:",font=("Helvetica", "20","bold"))
Username.grid(row=2, column=3,columnspan=2)
Password = tk.Label(self, text="Password:",font=("Helvetica", "20","bold"))
Password.grid(row=3, column=3,columnspan=2)
#............
Username_key = tk.Entry(self, textvariable = user_key, width=19, font=("Helvetica", "15"))
Username_key.grid(row=2, column=5,columnspan=5)
Password_key = tk.Entry(self, textvariable = psw_key, width=19, font=("Helvetica", "15"))
Password_key.grid(row=3, column=5,columnspan=5)
log_in = tk.Button(self, width=7, text="Log In", command=lambda: controller.show_frame("StorageOrMotor"))
log_in.grid(row=5,column=8,columnspan=2)
#............`I try to create a clear button`
Clear = tk.Button(self, width=7, text=" Clear " ,command=lambda:clear_message())
Clear.grid(row=5,column=5,columnspan=2)
clear_message() belongs to MainPage class so when calling it inside that class, you need to use self. prefix. Also, you need to use self as a parameter when defining the method since it is a member of a class.
def clear_message(self): #self here
user_key.delete(0, 'END')
psw_key.delete(0, 'END')
Additionally, since clear_message doesn't take any arguments, you don't need a lambda expression there.
#self here and removed lambda
Clear = tk.Button(self, width=7, text=" Clear " ,command=self.clear_message)

Resources