简体   繁体   中英

Python/Tkinter OptionMenu Update creates a “Shadow” of the Menu

So I'm still quite new to this (my code should make this obvious) and I am working on a GUI with tkinter. I am trying to have an OptionMenu which shows Keys from a dict and and upon clicking on a key I would like to see the value. I want to modify that dict and would like to be able to update said OptionMenu.

So far, so good. Now I've been able to get this to "work" - but when I update the menu (after changing it or not) I get a shadow of the menu itself.

I've conconcted a small test program:

import tkinter as tk
from tkinter import ttk

class MyApp():

    def __init__(self,master):

        self.master = master
        self.myDict =  {'Key1':1, 'Key2': 2, 'Key3':3}


        self.valueVar = tk.StringVar()
        self.valueVar.set("0.00")

        self.RCS = tk.Label(master, textvariable=self.valueVar).grid(row=5, column=3)

        updateButton = tk.Button(text= "Update List", command =  self.update)
        updateButton.grid(row=4,column=4)

        changeButton = tk.Button(text= "Change list", command =  self.changeDict)
        changeButton.grid(row=5,column=4)


        self.keyVar = tk.StringVar(master)

        self.om = ttk.OptionMenu(self.master, self.keyVar, "Select Key ", *self.myDict, command = self.setKey )
        self.om.configure(width=20)
        self.om.grid(row=4, column=3)

    def setKey(self,Surface):
        self.valueVar.set(self.myDict[Surface])

    def update(self):
        menu = self.om["menu"]
        menu.delete(0,"end")
        menu.destroy
        menu = ttk.OptionMenu(self.master, self.keyVar, "Select Key", *self.myDict, command = self.setKey )
        menu.grid(row=4, column=3)

    def changeDict(self):
        self.myDict =  {'Key4':4, 'Key5': 5, 'Key6':6}

root = tk.Tk()
app = MyApp(root)
root.mainloop()

What do I have to change? Why? Usually I work with Matlab. I guess it shows.

Much appreciated!

As far as I understand this mini-program you which for it to display an optionmenu with the keys of a dict and then when you press "change dict" and then update it should switch the optionmenu to the other set of items? In this case, you were calling the destroy on the wrong widget. The only issue was with the update function which should be changed to:

def update(self):
        #menu = self.om["menu"]
        #menu.delete(0,"end")
        #The above two menu items are not neede dif you are just going to destroy the widget
        self.om.destroy()
        self.om = ttk.OptionMenu(self.master, self.keyVar, "Select Key", *self.myDict, command = self.setKey )
        self.om.configure(width=20)
        self.om.grid(row=4, column=3)

This will do what I think you want it to do. Just so you know, the optionmenu widget is actually a combination of a button and a menu widget. So when you do menu = self.om["menu"], you are actually getting the menu object of the optionmenu widget and then destroying that. Then you are replacing that variable with an optionmenu and losing the original menu whilst not destroying the original optionmenu (self.om). This is why you got the shadow. Some other notes though:

  1. There is no need for the user to have to press 2 buttons when switching lists - call the update function from the changedict function so that it automatically populates.
  2. You can iterate over the menu items as you began to do but you need to decide on one or the other. I can't comment on the efficiency of completely destroying and enabling the widget or changing the menu items of the current widget as I am still rather experienced.

Hopefully that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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