简体   繁体   English

Python 从带有参数的列表中创建 tkinter class 的唯一实例

[英]Python create unique instances of a tkinter class from a list with parameters

I'm helping clean up some code for a senior design project.我正在帮助清理高级设计项目的一些代码。 The students have a python app that is using tkinter to create a GUI for inventory control and vending product.学生有一个 python 应用程序,它使用 tkinter 创建用于库存控制和自动售货产品的 GUI。 I don't want to post a ton of code but hope to portray what I'm trying to do.我不想发布大量代码,但希望描述我正在尝试做的事情。

Description of what is below: BinA, BinB, BinC,and BinD are all the same but with unique variable passed in, A bin class was created in a new document called pages.py.以下内容的描述:BinA、BinB、BinC 和 BinD 都是相同的,但传入了唯一的变量,在名为 pages.py 的新文档中创建了一个 bin class。 These are created at the bottom of the main program with their variables.这些是在主程序的底部使用它们的变量创建的。 Then I put them in a framesList along with other pages the application will navigate through.然后我将它们与应用程序将浏览的其他页面一起放入 framesList 中。 All the other frames in the list are currently unique hard-coded classes in the code or we will want to apply the solution I'm struggling with if we get it working.列表中的所有其他框架目前都是代码中唯一的硬编码类,或者如果我们让它工作,我们将希望应用我正在努力解决的解决方案。

When Bin(AD) all had unique hard-coded self named classes that had identical code in them other than the few parameters we identified, screen navigation operated as expected, but creating 4 instances of pages.bin and iterating through the list of frames results in only having what appears to be 4 pages.bin with only the last created variables.当 Bin(AD) 都具有唯一的硬编码自命名类时,除了我们识别的几个参数之外,它们具有相同的代码,屏幕导航按预期运行,但创建 4 个 pages.bin 实例并遍历框架结果列表只有看起来只有最后创建的变量的 4 pages.bin。 You can see after for F in frameList: the show self.show_frame(BinA) is called, but the first element in the LinkList is a string the populates a label on the screen.您可以for F in frameList:调用了 show self.show_frame(BinA) ,但是 LinkList 中的第一个元素是一个字符串,它在屏幕上填充了一个 label。 This label only show what ever the last frame was created of the Pages.bin.这个 label 只显示了 Pages.bin 的最后一帧是什么。 type.类型。 The other screen are all created correctly and function. Just navigating back to screen Bin(?) always behaves like BinD in this case.其他屏幕均已正确创建且为 function。在这种情况下,只需导航回屏幕 Bin(?) 始终表现得像 BinD。 If I create them in reverse order D,C,B,A then BinA is the result for all four.如果我以相反的顺序创建它们 D,C,B,A 那么 BinA 是所有四个的结果。

I suspect what is happeing is we are only creating one instance of pages.Bin and simply overwriting it in each loop of for F in frameList: but the other are ok because they are all unique Classes.我怀疑正在发生的事情是我们只创建了一个 pages.Bin 实例,并for F in frameList:每个循环中简单地覆盖它:但另一个没问题,因为它们都是唯一的类。

import tkinter as tk
from tkinter import *
import random
import time
import csv
import openpyxl
import pages

#get Display Size
root = tk.Tk()
screen_width = root.winfo_screenwidth() #1440
screen_height = root.winfo_screenheight() #900
#Close the popup
root.destroy()

print('Width: %i px, height: %i px' %(screen_width, screen_height))


#Create the main Application
class CMGUI(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "CMA: AutoBox")
        tk.Tk.wm_resizable(self,0,0)
        tk.Tk.wm_overrideredirect(self,False)#True) //Use this on the final
        container = tk.Frame(self)       
        container.pack(side="top", fill="both", expand=True)
        container.grid_columnconfigure(0, weight=1)
        container.grid_rowconfigure(0, weight=1)
        

        self.frames = {}

        #Declart the Objects

        # Put them in a List
        frameList =    [[BinA       ,BinA_linksList],
                        [BinB       ,BinB_linksList],
                        [BinC       ,BinC_linksList],
                        [BinD       ,BinD_linksList],
                        [HomePage   ,None],
                        [PPE        ,None],
                        [Weld       ,None],
                        [Misc       ,None],
                        [Set        ,None],
                        [PPE2       ,None],
                        [Weld2      ,None],
                        [Misc2      ,None],
                        [AllItems   ,None],
                        [BinType    ,None],
                        [Inventory  ,None],
                        [LoginPage  ,None]]

        for F in frameList:             
        #   frame = F(parent=container, controller=self)
            frame = F[0](container, self, F[1])
            self.frames[F[0]] = frame
            frame.grid(row=0, column=0, sticky="nsew")
            frame.configure(bg='deepskyblue')


        self.show_frame(BinA) 
....
class LoginPage(tk.Frame):
     def __init__(self, parent, controller,*args):
        tk.Frame.__init__(self, parent)
        ....

class HomePage(tk.Frame):
    def __init__(self, parent, controller,*args):
        tk.Frame.__init__(self, parent)
        ....

class AllItems(tk.Frame):
    def __init__(self, parent, controller,*args):
        tk.Frame.__init__(self, parent)
        .....

ALLOT OF other CODE creating the other page classes like BinType, HomePage, PPE, and more
....

#Create 4 pages for bins
# Bin? = pages.Bin
# Bin?_linkList = ["Label"  ,return_Link ,Link_1    ,Link_2     ,Link_3     ,Link_4]

BinA = pages.Bin
BinA_linksList = ["Bin A"   ,BinType    ,HomePage   ,PPE        ,PPE        ,PPE]

BinB = pages.Bin
BinB_linksList = ["Bin B"   ,BinType    ,PPE        ,HomePage   ,PPE    ,PPE]

BinC = pages.Bin
BinC_linksList = ["Bin C"   ,BinType    ,PPE        ,PPE        ,HomePage   ,PPE]

BinD = pages.Bin
BinD_linksList = ["Bin D"   ,BinType    ,PPE        ,PPE        ,PPE    ,HomePage]


w = str(screen_width)
h = str(screen_height)
z = str("+0+0")
screenres = w+'x'+h+z

app = CMGUI()
app.geometry(screenres)
app.mainloop()
root.destroy

pages.py页面.py

import tkinter as tk

class Bin(tk.Frame):

    def __init__(self, parent, controller, data):
     
        print(data[0])
        tk.Frame.__init__(self, parent)
        
        # Header Label        
        tk.Label(self, font=('times', 50, 'bold'), 
            text=data[0], fg="deepskyblue", bd=20, anchor='center', 
            bg="black", relief="ridge").place(anchor = "n", relx = .5, y =0)
        
        # Footer Label
        tk.Label(self, font=('times',22,'bold'), 
            text="Page 1", bg="deepskyblue", fg="black").place(anchor = "s", relx = .5, rely = .95)

        #Buttons:
        #mylist =   [["Title"]                  , page      , "anchor"  , %x    ,  %y   ],
        btnList =   [["Search By\n Bin Type"    , data[0]   , "ne"      , .95   , .05   ],
                    ["Back to\n Categories"     , data[1]   , "nw"      , .05   , .05   ]]
                    
        for b in btnList:
            tk.Button(self, padx=5, pady=5, bd=16, fg="white", font=('times',24,'bold'), width=8, height=2,
                  text=b[0], bg="black", relief="raised",
                  command = lambda i=b[1]: controller.show_frame(i)).place(anchor = b[2],relx = b[3], rely = b[4])

        btnList2 =   [["Item 1"   , data[2]   , "se"      , .5   , .5   ],
                     ["Item 2"    , data[3]   , "sw"      , .5   , .5   ],
                     ["Item 3"    , data[4]   , "ne"      , .5   , .5   ],
                     ["Item 4"    , data[5]   , "nw"      , .5   , .5   ]]
                
        for b in btnList2:
            tk.Button(self, padx=5, pady=5, bd=16, fg="white", font=('times',24,'bold'), width=9, height=3,
                  text=b[0], bg="black", relief="raised",
                  command = lambda i=b[1]: controller.show_frame(i)).place(anchor = b[2],relx = b[3], rely = b[4])

BinA, BinB, BinC,and BinD are all literally the same object: Bin. BinA、BinB、BinC 和 BinD 完全相同 object:Bin。 To boil down your code to simplest terms, what do you expect the output of this is?将您的代码归结为最简单的术语,您期望 output 是什么?

data = 'spam'
BinA = data
BinB = data
BinC = data
BinD = data

frames = {}
for F in (BinA, BinB, BinC, BinD):
    frames[F] = 42

print(frames) # what do you expect this to print? 

Try that and see, and you'll understand your problem.试试看,你就会明白你的问题。

The simple solution is to replace简单的解决方案是更换

BinA = pages.Bin

with

class BinA(pages.Bin): pass

Thereby creating a unique object.从而创造出独一无二的object。

But that's not clean at all.但这根本不干净。 To clean it you would pick a different metric to store your pages with, and at the same time move to a modern inheritance style and remove the useless controller frame.要清理它,您可以选择一个不同的指标来存储您的页面,同时移动到现代 inheritance 样式并删除无用的 controller 框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM