Tkinter OptionMenu小部件未显示值

时间:2017-04-09 01:22:01

标签: python tkinter optionmenu

目前我正在使用Python 3.6 Tkinter开发一个项目。目前,我正在尝试为用户设置用户访问权限OptionMenu,以便用户使用"用户"或"管理员"。我尝试了各种方法,但似乎无法自己修复或在线查找有用的文档。 问题不在于制作OptionMenu并显示它,也不是StringVar变量的值不会改变。问题是,当选择任何新选项时,OptionMenu内部的文本不会改变。

class UsersDetailsEditPage(Tk):
def __init__(self, *args, **kwargs):
    Tk.__init__(self, *args, **kwargs)
    self.title("Edit User Details")
    self.option_add("*Font", 'TkDefaultFont')

    self.noteBook = ttk.Notebook(self)

    for i in range(len(users)):
        self.noteBook.add(self.getUserViewFrame(users[i]), text=users[i][2])
    self.noteBook.pack()

    self.resizable(width=False, height=False)

def getUserViewFrame(self, user):
    frame = Frame(self)
    frame.grid_rowconfigure(1, weight=1)
    frame.grid_columnconfigure(1, weight=1)

    Label(frame, text="User's name:").grid(row=0, column=0, sticky=W)
    nameText = Text(frame, height=1, width=20)
    nameText.insert("1.0", user[2])
    nameText.edit_reset()
    nameText.grid(row=0, column=1, sticky=E)

    Label(frame, text="Username:").grid(row=1, column=0, sticky=W)
    usernameText = Text(frame, height=1, width=20)
    usernameText.insert("1.0", user[0])
    usernameText.edit_reset()
    usernameText.grid(row=1, column=1, sticky=E)

    Label(frame, text="Password:").grid(row=2, column=0, sticky=W)
    passwordText = Text(frame, height=1, width=20)
    passwordText.insert("1.0", user[1])
    passwordText.edit_reset()
    passwordText.grid(row=2, column=1, sticky=E)

    # the constructor syntax is:
    # OptionMenu(master, variable, *values)

    Label(frame, text="User Access:").grid(row=3, column=0, sticky=W)
    self.options = StringVar()
    self.options.set("User")

    self.userAccessDrop = ttk.OptionMenu(frame, self.options, "User", *("User", "Admin"))
    self.userAccessDrop.config(width=10)
    self.userAccessDrop.grid(row=3, column=1, sticky=E)

    return frame

This is the output of the code

我有所需的所有库导入(我认为):

from tkinter import *
from tkinter import messagebox
import tkinter.ttk as ttk
import csv
import os

如果有人能够知道如何完成这项工作,我将不胜感激。 感谢

1 个答案:

答案 0 :(得分:1)

我尝试了你的代码,它对我有用。我只能猜测这是一个垃圾收集问题。尝试将选项菜单分配给框架而不是自己,以便不会被覆盖。

frame.options = StringVar()
frame.options.set("User")

frame.userAccessDrop = ttk.OptionMenu(frame, frame.options, "User", *("User", "Admin"))
frame.userAccessDrop.config(width=10)
frame.userAccessDrop.grid(row=3, column=1, sticky=E)

你真的应该重写这个,以便你将一个Frame子类化为用户实例。

编辑:例如:

import tkinter as tk
from tkinter import ttk

class UserFrame(tk.Frame):
    def __init__(self, master=None, data=None, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)

        data = data[2], data[0], data[1] # rearrange data
        labels = ("User's name:", "Username:", "Password:")
        for row, (label, value) in enumerate(zip(labels, data)):
            lbl = tk.Label(self, text=label)
            lbl.grid(row=row, column=0, sticky=tk.W)
            ent = tk.Entry(self)
            ent.insert(0, value)
            ent.grid(row=row, column=1, sticky=tk.E)

        lbl = tk.Label(self, text="User Access:")
        lbl.grid(row=3, column=0, sticky=tk.W)
        self.options = tk.StringVar(self, "User")

        self.userAccessDrop = ttk.OptionMenu(self,
            self.options,
            "User", # starting value
            "User", "Admin", # options
            )
        self.userAccessDrop.config(width=10)
        self.userAccessDrop.grid(row=len(labels), column=1, sticky=tk.E)

class UsersDetailsEditPage(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.title("Edit User Details")
        self.option_add("*Font", 'TkDefaultFont')

        self.noteBook = ttk.Notebook(self)

        for user in users:
            self.noteBook.add(UserFrame(self, user), text=user[2])
        self.noteBook.pack()

        self.resizable(width=False, height=False)

它与你所拥有的功能完全不同,只是更简洁的代码(实际上在编码时间上有很大差异)。注意我也摆脱了邪恶的通配符导入并稍微压缩了你的代码。请记住,如果您正在复制和粘贴代码块,那么您正在执行计算机的工作。我还将您转移到Entry小部件,这是一个单行文本小部件。此外,尽量避免“方便”初始化并在同一行上布置小部件。它很难看,它会导致错误。

我使用'self'来表示“self.options”和“self.userAccessDrop”,但由于我们将子类化为Frame,“self”现在引用了Frame实例。换句话说,它与我使用“frame.options”的上面的块相同。