在tkinter中使用class时出错? (OOP)

时间:2017-12-12 14:17:15

标签: python tkinter

我想显示一个选项菜单,其中有多个选项可供选择。 editionMap,topicMap,langMap都是字典。我正在尝试制作一个选项菜单,然后制作它的实例。

import tkinter as tk
from utils import editionMap, topicMap, langMap

class OptionMenu:
    """Constructor Function"""
    def __init__(self, master, status, *options):
        self.frame = Frame(master)
        frame.pack()

        self.dropdown = tk.StringVar()
        self.dropdown.set("status")


def main():
    root = tk.Tk()
    menu1 = OptionMenu(root, "Language", *langMap.keys())
    menu1.pack()
    root.mainloop()

if __name__ == '__main__':
    main()

我想使用类制作optionsmenu(见截图):

enter image description here

在创建类OptionMenu时,我收到错误,只打开GUI窗口,这是空白

 Traceback (most recent call last):
  File "F:\KWOC gnewsclient\gnewsclient\gnewsclient\test.py", line 22, in <module>
    main()
  File "F:\KWOC gnewsclient\gnewsclient\gnewsclient\test.py", line 18, in main
    menu1.pack()
AttributeError: 'OptionMenu' object has no attribute 'pack'

1 个答案:

答案 0 :(得分:1)

您在OptionMenu内创建自己的Frame,但没有原始tk.OptionMenu

import tkinter as tk

langMap = {1:"English", 2:"German", 3:"Russian"}

class MyOptionMenu1():  # <-- without inheritions it is not widget, 
                        # You can't use `menu1.pack()`.
                        # You could use only `menu1.frame.pack()`.
                        # Or you have to create own `def pack(self, **options)
                        #    and execute `self.frame.pack()` inside

    def __init__(self, master, status, *options):

        self.frame = tk.Frame(master) # <-- tk.
        self.frame.pack() # <-- self.

        self.result = tk.StringVar()
        #self.result.set(status)

        self.label = tk.Label(self.frame, text=status)
        self.label.pack()

        self.dropdown = tk.OptionMenu(self.frame, self.result, *options)
        self.dropdown.pack()


class MyOptionMenu2(tk.Frame): # <-- inherits from Frame

    def __init__(self, master, status, *options):

        super().__init__(master) # Frame constructor
        #self.pack() # <-- without - use `menu1.pack()` to show this frame 

        self.result = tk.StringVar()
        #self.result.set(status)

        self.label = tk.Label(self, text=status) # <-- self as parent/master
        self.label.pack()

        self.dropdown = tk.OptionMenu(self, self.result, *options) # <-- self as parent/master
        self.dropdown.pack()


def main():
    root = tk.Tk()

    # --- version 1 ---

    menu1 = MyOptionMenu1(root, "Language", *langMap.keys()) # <-- tk.
    #menu1.pack() # <--- without, because MyOptionMenu1 is not widget

    menu1 = MyOptionMenu1(root, "Language", *langMap.values()) # <-- tk.
    #menu1.pack() # <--- without, because MyOptionMenu1 is not widget

    # --- version 2 ---

    menu1 = MyOptionMenu2(root, "Language", *langMap.keys()) # <-- tk.
    menu1.pack() # <--- with, because MyOptionMenu2 is widget 

    menu1 = MyOptionMenu2(root, "Language", *langMap.values()) # <-- tk.
    menu1.pack() # <--- without, because MyOptionMenu is not widget

    root.mainloop()

if __name__ == '__main__':
    main()

编辑代码,其中包含布局更改但没有注释

import tkinter as tk

class MyOptionMenu1(): # <-- not inherits from Frame 

    def __init__(self, master, status, *options):

        self.frame = tk.Frame(master) # internal class
        self.frame.pack(anchor='w') # show in window

        self.result = tk.StringVar(value=options[0])

        self.label = tk.Label(self.frame, text=status)
        self.label.pack(side='left')

        self.dropdown = tk.OptionMenu(self.frame, self.result, *options)
        self.dropdown.pack()


class MyOptionMenu2(tk.Frame): # <-- inherits from Frame

    def __init__(self, master, status, *options):

        super().__init__(master) # Frame constructor
        #self.pack(anchor='w') # show in window (but you can do it outside

        self.result = tk.StringVar(value=options[0])

        self.label = tk.Label(self, text=status) # <-- self as parent/master
        self.label.pack(side='left')

        self.dropdown = tk.OptionMenu(self, self.result, *options) # <-- self as parent/master
        self.dropdown.pack()


if __name__ == '__main__':

    langMap = {1:"English", 2:"German", 3:"Russian"}

    root = tk.Tk()

    # --- version 1 ---

    menu = MyOptionMenu1(root, "Language", *langMap.keys())
    #menu.pack() # <--- without pack(),
                 # because MyOptionMenu1 is not widget
                 # and it doesn't have this method

    menu = MyOptionMenu1(root, "Language", *langMap.values())
    #menu.pack() # <--- without pack(),
                 # because MyOptionMenu1 is not widget
                 # and it doesn't have this method

    # --- version 2 ---

    menu = MyOptionMenu2(root, "Language", *langMap.keys())
    menu.pack(anchor='w') # <--- with pack()
                          # because MyOptionMenu2 is widget 

    menu = MyOptionMenu2(root, "Language", *langMap.values())
    menu.pack(anchor='w') # <--- with pack()
                          # because MyOptionMenu2 is widget

    # --- start ---

    root.mainloop()

enter image description here