Reputation: 191
I am in need of help in solving this issue, I know is a long post but this issue is hitting me for a while, and I searched for hours for an answer without a solution.
I am developing a Tkinter software with some windows to the user to navigate through. Each window will have a set of questions to be answered and the objective is to save all those answers into a separate file. For easiness of maintenance, I developed each window in a different file so I can track back easier errors and changes to the windows themselves.
I don't believe the issue lays with using Tkinter itself, but I am inserting all the code (1 window creation and 2 classes for defining the questionnaires) so it is a valid running code.
If I isolate one questionnaire and create a window = tk.Tk()
to test it, I can use de variable, but with the presented architecture no.
My window creation code is:
import tkinter as tk, Questions1 as q1, Questions2 as q2
#Software initial_class
class HAS(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, *kwargs)
#Page configure
tk.Tk.wm_title(self, "Checklist")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.configure(background = "white")
#Adding overhead menu
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar, tearoff = 0)
filemenu.add_command(label = "Save", command = print("In development"))
filemenu.add_command(label = "Exit", command= self.destroy)
menubar.add_cascade(label="File", menu=filemenu)
tk.Tk.config(self, menu=menubar)
#Defining the page_frames
self.frames = {}
for F in (q1.Q1, q2.Q2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(q1.Q1)
#showing the selected frame
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
app = HAS()
app.geometry("530x700")
app.mainloop()
My First Questionaire page is:
import tkinter as tk
from tkinter import ttk
FONT = ("Arial", 11)
choices_y_n = ['-', 'Yes', 'No']
Questionlist_a = ["A. Is true?:", "B. Is True? :","C. Is True? :", "D. True? :"]
def save_values():
global y
y = list(map(lambda x: x.get(), qt))
print(y)
class Q1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.columnconfigure(0, minsize=100)
self.columnconfigure(1, minsize=150)
self.columnconfigure(2, minsize=50)
#Header Config
tk.Frame.configure(self, background = "white")
#tk.Label(self, image=Logo, background="white").grid(row=0, column=0, padx=100, columnspan=3, pady=10, sticky="W")
ttk.Label(self, text="1st Checklist", font = FONT, background = "white").grid(row=1, column=0, columnspan=3, pady = 10)
ttk.Label(self, text="Questions: ", background="white").grid(row=2, column=0,columnspan=2, padx=10, pady = 10, sticky="W")
#Questions
global qt
qt = [tk.StringVar(self) for i in range(len(Questionlist_a))]
for r in range(len(Questionlist_a)):
ttk.Label(self, text=Questionlist_a[r], background = "white").grid(row= r+3, column=0, columnspan=2, padx=10, pady = 10, sticky="W")
ttk.OptionMenu(self, qt[r], *choices_y_n).grid(row = r+3, column=2, padx=10, sticky="WE")
r=+1
#Buttons
ttk.Button(self, text="Save values", command = save_values, width=18).grid(row=16, column=0, padx=10, pady=15, sticky="W")
ttk.Button(self, text="Questions 2", command = lambda: controller.show_frame(__import__('Questions2').Q2),width=18).grid(row=17, column=0, padx=10, pady=15, sticky="W")
and my 2nd questionaire is:
import tkinter as tk
from tkinter import ttk
FONT = ("Arial", 11)
choices_y_n = ['-', 'Yes', 'No']
Questionlist_b = ["E. Is true?:", "F. Is True? :","G. Is True? :", "H. True? :"]
def save_values():
global y
y = list(map(lambda x: x.get(), qt))
print(y)
class Q2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.columnconfigure(0, minsize=100)
self.columnconfigure(1, minsize=150)
self.columnconfigure(2, minsize=50)
#Header Config
tk.Frame.configure(self, background = "white")
ttk.Label(self, text="2nd Checklist", font = FONT, background = "white").grid(row=1, column=0, columnspan=3, pady = 10)
ttk.Label(self, text="Questions: ", background="white").grid(row=2, column=0,columnspan=2, padx=10, pady = 10, sticky="W")
#Questions
global qt
qt = [tk.StringVar(self) for i in range(len(Questionlist_b))]
for r in range(len(Questionlist_b)):
ttk.Label(self, text=Questionlist_b[r], background = "white").grid(row= r+3, column=0, columnspan=2, padx=10, pady = 10, sticky="W")
ttk.OptionMenu(self, qt[r], *choices_y_n).grid(row = r+3, column=2, padx=10, sticky="WE")
r=+1
#Buttons
ttk.Button(self, text="Save values", command = save_values, width=18).grid(row=16, column=0, padx=10, pady=15, sticky="W")
ttk.Button(self, text="Questions 1", command = lambda: controller.show_frame(__import__('Questions1').Q1),width=18).grid(row=17, column=0, padx=10, pady=15, sticky="W")
This code is able to print the answers from the save_values
functions but I can't find a way to save those lists in a dictionary or a list of lists.
Can anyone help me with it?
Thanks alot!
Upvotes: 0
Views: 59
Reputation: 1826
If I understood it correctly, you want to access the saved answers from the master window. To do so, first you have to make the function save_values
a method of the Questions1
and Questions2
classes and create a property (I have named it self.list_answers
) to store the answers.
So, the first class code would be (questionnare two can be done the same way):
import tkinter as tk
from tkinter import ttk
FONT = ("Arial", 11)
choices_y_n = ['-', 'Yes', 'No']
Questionlist_a = ["A. Is true?:", "B. Is True? :","C. Is True? :", "D. True? :"]
class Q1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.columnconfigure(0, minsize=100)
self.columnconfigure(1, minsize=150)
self.columnconfigure(2, minsize=50)
#Header Config
tk.Frame.configure(self, background = "white")
#tk.Label(self, image=Logo, background="white").grid(row=0, column=0, padx=100, columnspan=3, pady=10, sticky="W")
ttk.Label(self, text="1st Checklist", font = FONT, background = "white").grid(row=1, column=0, columnspan=3, pady = 10)
ttk.Label(self, text="Questions: ", background="white").grid(row=2, column=0,columnspan=2, padx=10, pady = 10, sticky="W")
#Questions
global qt
qt = [tk.StringVar(self) for i in range(len(Questionlist_a))]
for r in range(len(Questionlist_a)):
ttk.Label(self, text=Questionlist_a[r], background = "white").grid(row= r+3, column=0, columnspan=2, padx=10, pady = 10, sticky="W")
ttk.OptionMenu(self, qt[r], *choices_y_n).grid(row = r+3, column=2, padx=10, sticky="WE")
r=+1
#Buttons
ttk.Button(self, text="Save values", command = self.save_values, width=18).grid(row=16, column=0, padx=10, pady=15, sticky="W")
ttk.Button(self, text="Questions 2", command = lambda: controller.show_frame(__import__('Questions2').Q2),width=18).grid(row=17, column=0, padx=10, pady=15, sticky="W")
# List of answers
self.list_answers=[]
def save_values(self):
self.list_answers = list(map(lambda x: x.get(), qt))
Then, you could access list_answers
outside the class. For instance, I have used the "Save" button of the filemenu to make a dictionary of the answers of both questionnares and print it with the following function:
# Function accessing the list of answers
def saveList(self):
dict_answers={'Answers 1': self.frames[q1.Q1].list_answers, "Answers 2": self.frames[q2.Q2].list_answers}
print(dict_answers)
Then, the complete code of the main window is left as follows:
import tkinter as tk, Questions1 as q1, Questions2 as q2
#Software initial_class
class HAS(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, *kwargs)
#Page configure
tk.Tk.wm_title(self, "Checklist")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
container.configure(background = "white")
#Adding overhead menu
menubar = tk.Menu(container)
filemenu = tk.Menu(menubar, tearoff = 0)
filemenu.add_command(label = "Save", command = self.saveList)
filemenu.add_command(label = "Exit", command= self.destroy)
menubar.add_cascade(label="File", menu=filemenu)
tk.Tk.config(self, menu=menubar)
#Defining the page_frames
self.frames = {}
for F in (q1.Q1, q2.Q2):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(q1.Q1)
#showing the selected frame
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
# Function accessing the list of answers
def saveList(self):
dict_answers={'Answers 1': self.frames[q1.Q1].list_answers, "Answers 2": self.frames[q2.Q2].list_answers}
print(dict_answers)
app = HAS()
app.geometry("530x700")
app.mainloop()
Then, you can save the answers that each questionnare has at each moment by pressing "Save" in the file menu. As an example, I have pressed "Save" before filling any questionnare, after having filled the first and, finally, after having filled the second one:
Upvotes: 1