我正在为stats报告生成器脚本创建一个GUI,但我很难让tkinter做我想做的事情。以下是完整的代码。基本上,有一个控制两个堆叠帧(页面)的应用程序。第一页是您在报告中输入所需的一些基础知识,例如产品,年份,季度和地区。我希望在第一页上选择的区域决定在第二页上显示哪个国家/地区复选框。有一个名为country_lists()的函数接收该区域并返回该区域的国家/地区。 selected_region是包含第1页上选择的区域的全局变量。
问题是,第2页是在第1页上选择selected_region之前启动的,因此我无法在第2页上显示正确的国家/地区。
现在我必须手动分配区域以便脚本运行。例如: selected_region ='亚太地区'
然后,一旦脚本运行,我就会对此进行评论,并使用selected_region对脚本进行排序,但它使用上次运行脚本时的selected_region(使用之前的全局值)。我希望page2显示新选区域中国家/地区的复选框。
我已经将页面2 init移动到initUI中的multCommands函数中,但它只产生了一个空白的第二页。例如:
if selected_product == "All":
self.initPage2(page)
self.callback()
else:
try:
self.close_window()
except:
pass
我还是tkinter的新手,所以我发现很难理解我需要做些什么来使这项工作。任何帮助表示赞赏!
from Tkinter import *
import tkMessageBox
import tkFileDialog
productList = ['All', 'VV', 'NG', 'Traffic', 'Hypothetical']
regionList = ['APAC', 'AU', 'NA', 'SAM', 'India', 'EEU', 'WEU', 'MEA', 'TWN', 'ROW']
quarterList = ['Q1', 'Q2', 'Q3', 'Q4']
yearList = ['2013', '2014', '2015', '2016']
selected_country_list = []
EEU_country_codes = { 'Czech Republic':'C0', 'Greece':'GR', 'Hungary':'H1', 'Poland':'P0', 'Russia':'R0', 'Slovakia':'M2', 'Turkey':'T0', 'Ukraine':'U0'}
MEA_country_codes = { 'Bahrain':'WG', 'Israel':'IS', 'Jordan':'JO', 'Kuwait':'WD', 'Lebanon':'LB','Oman':'WF', 'Qatar':'WC', 'Saudi Arabia':'WH', 'South Africa':'L0', 'UAE':'WE'}
WEU_country_codes = { 'Austria':'A1', 'Andorra':'ZG', 'Belgium':'BB', 'Denmark':'S4', 'Finland':'FI', 'France':'F0', 'Germany':'G0', 'Ireland':'EB', 'Italy':'I0', 'Liechtenstein':'ZL', 'Luxembourg':'LU', 'Malta':'M9','Monaco':'MC', 'Netherlands':'N3', 'Norway':'N1', 'Portugal':'KA', 'San Marino':'MZ','Spain':'KE','Sweden':'S0','Switzerland':'CA', 'United Kingdom':'ED', 'Vatican City':'VS', 'Gibraltar':'K2'}
SAM_country_codes = { 'Brazil':'SB', 'Argentina':'W3', 'Chile':'C6', 'Colombia':'CB', 'Costa Rica':'CR', 'Panama':'PB', 'Peru':'PE', 'Uruguay':'UY'}
NA_country_codes = { 'United States':'US', 'Mexico':'MX', 'Canada':'DB', 'Puerto Rico':'94', 'US Virgin Islands':'94' }
APAC_country_codes = { 'Indonesia':'UF', 'Malaysia':'W2', 'Singapore':'W1', 'Thailand':'JN'}
TWN_country_codes = { 'Taiwan':'VD'}
India_country_codes = { 'India':'5R'}
AU_country_codes = { 'Australia':'AU', 'New Zealand':'NZ'}
ROW_country_codes = {}
ROW_country_codes.update(APAC_country_codes)
ROW_country_codes.update(AU_country_codes)
ROW_country_codes.update(India_country_codes)
ROW_country_codes.update(TWN_country_codes)
region_country_hash = { 'SAM': SAM_country_codes, 'NA': NA_country_codes, 'APAC': APAC_country_codes, 'India': India_country_codes,'AU': AU_country_codes, 'ROW': ROW_country_codes, 'EEU': EEU_country_codes, 'WEU': WEU_country_codes, 'MEA': MEA_country_codes, 'EU': EU_country_codes, 'TWN': TWN_country_codes}
#------------------------------------------------------------------------
def country_lists(region):
use_hash = region_country_hash[region]
# convert to an array
region_country_list = []
for k, v in sorted(use_hash.iteritems()):
region_country_list.append(k)
if len(region_country_list) > 1:
region_country_list.append('All')
current_country_list = region_country_list[0:8]
current_country_list1 = region_country_list[8:16]
current_country_list2 = region_country_list[16:24]
return current_country_list, current_country_list1, current_country_list2
#------------------------------------------------------------------------
class Page(Frame):
def __init__(self, parent, page, *args, **kwargs):
Frame.__init__(self, *args, borderwidth=0, **kwargs)
self.parent = parent
self.pack(fill=BOTH, expand=1)
self.columnconfigure(0, weight = 1)
self.centerWindow()
if page == "p1":
self.initUI(page)
else:
self.initPage2(page)
def initUI(self, page):
root.title("Stats Aggregator")
windowBorder = LabelFrame(self, text=" Choose data to compare: ", padx=0, pady=0, width=740,height=260)
windowBorder.grid(row = 0, column = 0, pady=10, padx=10, columnspan = 2, rowspan = 4, sticky='NW')
region = StringVar()
qtr = StringVar()
month = StringVar()
year = StringVar()
product = StringVar()
version = StringVar()
select_width = 48
product.set('Select Product:') # default value
S = OptionMenu(self, product, *productList)
S.config(width=select_width)
S.pack( side = LEFT)
S.grid(row = 1, column = 0, pady=10, padx=20, sticky='NW')
region.set('Select Region:') # default value
O = OptionMenu(self, region, *regionList)
O.config(width=select_width)
O.pack( side = LEFT)
O.grid(row = 1, column = 1, pady=10, padx=20, sticky='NW')
qtr.set('Select Quarter:') # default value
P = OptionMenu(self, qtr, *quarterList)
P.config(width=select_width)
P.pack( side = LEFT)
P.grid(row = 2, column = 0, pady=10, padx=20, sticky='NW')
year.set('Select Year:') # default value
R = OptionMenu(self, year, *yearList)
R.config(width=select_width)
R.pack( side = LEFT)
R.grid(row = 2, column = 1, pady=10, padx=20, sticky='NW')
submitButton = LabelFrame(self, text="", padx=0, pady=0, width=740,height=80)
submitButton.grid(row = 4, column = 0, pady=10, padx=10, columnspan = 2, sticky='NW')
Button(self, text = ' Submit ', command = lambda: multCommands(region, qtr, product, year)).grid(row = 4, columnspan = 2, pady=35, padx=15, sticky='N')
def multCommands(region, qtr, product, year):
global selected_region
global selected_qtr
global selected_product
global selected_year
global selected_country_list
region = str(region.get())
qtr = str(qtr.get())
year = str(year.get())
product = str(product.get())
selected_region = region
selected_qtr = qtr
selected_product = product
selected_year = year
printInputs(selected_region, selected_qtr, selected_product, selected_year)
# This is the logic that determines whether or not to go on to a second
# page of inputs. A second page of inputs will appear (asking for version (placeholder))
# if the product selected is "All". Otherwise, the root window will close after one page of inputs.
# -------------------------------
if selected_product == "All":
self.callback()
else:
try:
self.close_window()
except:
pass
# -------------------------------
def printInputs(region, qtr, product, year):
print "The selected region is:", selected_region
print "The selected quarter is:", selected_qtr
print "The selected year is:", selected_year
print "The selected product is:", selected_product
def initPage2(self, page):
# selected_region = 'APAC'
# print "The selected region is:", selected_region
# returns a list of tuple containing three lists no longer than 8 elements each
country_list_tuple = country_lists(selected_region)
current_country_list = country_list_tuple[0]
current_country_list1 = country_list_tuple[1]
current_country_list2 = country_list_tuple[2]
list_len = len(current_country_list)
windowBorder = LabelFrame(self, text=" Choose countries to include: ", padx=0, pady=20, width=740,height=260, borderwidth=0)
windowBorder.grid(row = 0, column = 0, pady=10, padx=10, columnspan = 3, rowspan = list_len+1, sticky='W')
global selected_country_list
country_list0 = []
country_list1 = []
country_list2 = []
#----------------------------
def chkbox_checked(arg1, arg2, arg3):
global selected_country_list
consolidated_country_list = []
cb = arg1
cb_v = arg2
if arg3 == 0:
country_list = country_list0
if arg3 == 1:
country_list = country_list1
if arg3 == 2:
country_list = country_list2
for ix, item in enumerate(cb):
country_list[ix]=(cb_v[ix].get())
for i in country_list0:
consolidated_country_list.append(i)
for i in country_list1:
consolidated_country_list.append(i)
for i in country_list2:
consolidated_country_list.append(i)
print "consolidated_country_list:", consolidated_country_list, len(consolidated_country_list)
selected_country_list = consolidated_country_list
#----------------------------
checkbox_area0 = LabelFrame(windowBorder, text="", padx=0, pady=0, width=200,height=150, borderwidth=0)
checkbox_area0.grid(row = 1, column = 0, pady=0, padx=10, sticky='NW')
bb = []
bb_v = []
for ix, text in enumerate(current_country_list):
bb_v.append(StringVar())
off_value=''
bb.append(Checkbutton(checkbox_area0, text=text, onvalue=text, offvalue=off_value, variable=bb_v[ix], command= lambda: chkbox_checked(bb, bb_v, 0)))
bb[ix].grid(row=ix, column=0, padx=50, sticky='W')
country_list0.append(off_value)
bb[-1].deselect()
checkbox_area1 = LabelFrame(windowBorder, text="", padx=0, pady=0, width=200,height=150, borderwidth=0)
checkbox_area1.grid(row = 1, column = 1, pady=0, padx=10, sticky='NW')
#column 1
if current_country_list1:
cb = []
cb_v = []
for ix, text in enumerate(current_country_list1):
cb_v.append(StringVar())
off_value=''
cb.append(Checkbutton(checkbox_area1, text=text, onvalue=text, offvalue=off_value, variable=cb_v[ix], command= lambda: chkbox_checked(cb, cb_v, 1)))
cb[ix].grid(row=ix, column=0, padx=50, sticky='W')
country_list1.append(off_value)
cb[-1].deselect()
checkbox_area2 = LabelFrame(windowBorder, text="", padx=0, pady=0, width=200,height=150, borderwidth=0)
checkbox_area2.grid(row = 1, column = 2, pady=0, padx=10, sticky='NW')
#column 2
if current_country_list2:
db = []
db_v = []
for ix, text in enumerate(current_country_list2):
db_v.append(StringVar())
off_value=''
db.append(Checkbutton(checkbox_area2, text=text, onvalue=text, offvalue=off_value, variable=db_v[ix], command= lambda: chkbox_checked(db, db_v, 2)))
db[ix].grid(row=ix, column=0, padx=50, sticky='W')
country_list2.append(off_value)
db[-1].deselect()
submitButton = LabelFrame(self, text="", padx=0, pady=0, width=740,height=80, borderwidth=0)
submitButton.grid(row = list_len+1, column = 0, pady=10, padx=10, columnspan = 3, sticky='NW')
Button(self, text = ' Generate Reports ', command = lambda: multCommands2(selected_country_list)).grid(row = list_len+1, columnspan = 3, pady=35, padx=15, sticky='N')
def multCommands2(selected_country_list):
self.callback()
printInputs2(selected_country_list)
def printInputs2(selected_country_list):
print "The selected countries are:", selected_country_list, len(selected_country_list)
def centerWindow(self):
w = 760
h = 380
sw = root.winfo_screenwidth()
sh = root.winfo_screenheight()
x = (sw - w)/2
y = (sh - h)/2
root.geometry('%dx%d+%d+%d' % (w,h, x, y))
def onlift(self):
self.lift()
def close_window(self):
root.destroy()
#------------------------------------------------------------------------
class App(Frame):
def __init__(self, *args, **kwargs):
Frame.__init__(self, *args, **kwargs)
root.protocol("WM_DELETE_WINDOW", self.handler)
p1 = Page(self, 'p1')
p2 = Page(self, 'p2')
p1.callback = p2.onlift
p2.callback = p2.close_window
p1.place(x=0, y=0, relwidth=1, relheight=1)
p2.place(x=0, y=0, relwidth=1, relheight=1)
p1.onlift()
def handler(self):
if tkMessageBox.askokcancel("Quit?", "Are you sure you want to quit?"):
root.destroy()
print "Destoy root window."
self.master.quit()
print "Quit main loop."
sys.exit()
#------------------------------------------------------------------------
if __name__ == '__main__':
root = Tk()
root.resizable(0, 0)
app = App(root)
root.mainloop()
答案 0 :(得分:0)
你的程序结构非常偏斜。拥有类对象的重点是该类的所有实例都应该类似。因此,如果您确实选择为每个页面使用类,则它们应该是单独的类。
更好的方法如下:
Class App
def initPage1(self):
#Do all of page1 stuff here
def initPage2(self):
#Do all of page2 stuff here
OR 第1课 第2课 班级应用 def initPages(self): p1 = Page1() p2 = Page2()
至于更新页面,当在page1中更新值时,它应该调用一个处理程序。这个处理程序可以调用self.master.p2.update(updated_value)之类的东西,也可以调用self.master.update(updated_value),在这种情况下,App中的更新函数会调用p2中的更新函数。