我正在遵循Bryan在“在tkinter中切换两帧之间”的答案所做的MVC模型。他将框架堆叠在一起(所有框架都是在最开始制作)然后我们只是按照遗嘱展示它们。
我有两个简单的数据库表。第一个名为example_ini,有两列:lin_id和lin_option。表(1,2)中只有1个条目,它用于记住用户的最后一个选择,第二个是带有两列的example_options:lin_id和symbol。有4个条目(1,AA)(2,BB)(3,CC)和(4,DD)。我使用mysql,但我不认为这与问题有关。
只需打开和关闭代码即可更改数据库中的值。它看起来像是在页面制作时它在on_click中执行循环,而不应该。我怎么能阻止这种行为?
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
#import Tkinter as tk # python 2
#import tkFont as tkfont # python 2
from datetime import *
import mysql.connector
global __TBL_PREFIX__
__TBL_PREFIX__ = 'example_'
global config
config = {
'db' : 'example',
'user' : 'root',
'password' : '****', # Your password
}
class ini:
def __init__(self):
self.lin_id = None
self.lin_option = 0
# return an object populated based on the record's lin id
def getById(lin_id):
i = ini()
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
query = ("SELECT LIN_OPTION FROM %sINI WHERE LIN_ID = %d")
args = (__TBL_PREFIX__, lin_id)
query = query % args
cursor.execute(query)
results = cursor.fetchall()
cnx.commit()
if len(results) != 0 :
i.lin_option = results[0][0]
i.lin_id = lin_id
cursor.close()
cnx.close()
return i
# update an object in db
def update(i):
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
query = ('UPDATE %sINI SET LIN_OPTION = %d WHERE LIN_ID = %d')
args = (__TBL_PREFIX__, i.lin_option, i.lin_id)
query = query % args
cursor.execute (query)
cnx.commit()
cursor.close()
cnx.close()
return
class options:
def __init__(self):
self.lin_id = None
self.symbol = ''
# return an object populated based on the record's lin id
def getById(lin_id):
o = options()
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
query = ("SELECT SYMBOL FROM %sOPTIONS WHERE LIN_ID = %d")
args = (__TBL_PREFIX__, lin_id)
query = query % args
cursor.execute(query)
results = cursor.fetchall()
cnx.commit()
if len(results) != 0 :
o.symbol = results[0][0]
o.lin_id = lin_id
cursor.close()
cnx.close()
return o
# return all candidates
def getall():
cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
query = ("SELECT LIN_ID FROM %sOPTIONS")
args = (__TBL_PREFIX__)
query = query % args
cursor.execute(query)
result = [item[0] for item in cursor.fetchall()]
cursor.close()
cnx.close()
return result
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")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
self.container = tk.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 = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=self.container, controller=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("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
def add_new(self):
''' Create a new frame on the run '''
self.frames["StartPage"] = StartPage(parent=self.container, controller=self)
self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")
self.frames["PageOne"] = PageOne(parent=self.container, controller=self)
self.frames["PageOne"].grid(row=0, column=0, sticky="nsew")
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
i = ini.getById(1)
o = options.getById(i.lin_option)
text0 = 'Last option in database is ' + o.symbol
label = tk.Label(self, text=text0, font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One to change options",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two to update Page One",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
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. Press button to chance selection", font=controller.title_font)
label.grid(row=0, column=0)
i = ini.getById(1)
candidates = options.getall()
print(str(candidates))
Order = candidates.index(i.lin_option)
for counter, lin in enumerate(candidates):
file = 1 + counter # First counter is zero
print('Start file = ' + str(file))
print ('lin = ' + str(lin))
o = options.getById(lin)
print (' o = ' + str(o.lin_id) + ', ' + o.symbol)
# Cell 0
if Order == counter :
label = tk.Button(self, text=(counter+1), fg='red', state="disabled" )
else :
label = tk.Button(self, text=(counter+1), fg='blue', command= self.on_click(i, o.lin_id))
label.grid(row=file, column=0)
# Cell 1
if Order == counter :
label = tk.Label(self, text=o.symbol, font = 'Helvetica 28')
else :
label = tk.Label(self, text=o.symbol, font = 'Helvetica 12')
label.grid(row=file, column=1)
print ('End file = ' + str(file))
print ()
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.grid()
def on_click(self, i, lin_id):
print ('Change db values. OLD initial.lin_choise = ' + str(i.lin_option))
i.lin_option = lin_id
i.update()
print ('Change db values. NEW initial.lin_choise = ' + str(i.lin_option))
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button2 = tk.Button(self, text="Update page 1 and go to the start page",
command=self.on_click)
button1.pack()
button2.pack()
def on_click(self):
self.controller.add_new()
self.controller.show_frame("StartPage")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()