tkinter堆叠帧 - 第2帧需要反映第1帧中选择的内容

时间:2014-07-10 21:56:22

标签: python tkinter frames

我正在为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()

1 个答案:

答案 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中的更新函数。