Home > Mobile >  How to make python - tkinter dropdown command update after event
How to make python - tkinter dropdown command update after event

Time:01-06

I am remaking a GUI calculator app in Tkinter, in order to learn about classes, methods, attributes, and also to shorten my original code. In order to shorten the code, I made a frame class that generates frames, entries, labels and dropdown menus, so I don't have to create them individually. Everything went well until I got to the dropdown menu part. When the user selects a different option from the Filters - dropdown menu like V, or B or L etc. the value in frame 1 -> entry[1] doesn't update. The method that updates the value in that entry is called add(self) and it's a part of calculator class. Here is the simple version

import numpy as np
import tkinter as tk


window = tk.Tk()
window.geometry("920x500")
window.resizable(0,0)
window.title('Exposure Time Calculator')


class Calculator:
    
    def __init__(self, window):
        
        self.create_test_frame1()
        self.create_test_frame2()
        self.add(None)
        
    def create_test_frame1(self):
        
        labelvalues=['val 1','val 2']
        entryvalues=['203','1333']
        self.frame_1 = frame('Test Frame 1',labelvalues,entryvalues,6, 2, 0, 0, "no",0,0,0,0,0,30,40)

    def create_test_frame2(self):
        labelvalues = ['val 3','val 4']
        entryvalues = ['10','24.5']
        option_menu_values = ['B','V','R','I','Luminance','Hydrogen 3nm']
        
       
        
        self.frame_2 = frame('Frame 2', labelvalues, entryvalues, 14, 2, 0, 2, 
                                  "option_menu1_yes", option_menu_values,'Filters',
                                  0,0,0,
                                  5,20)
    
    def add(self, e):
       
       qe = self.frame_1.entry[1]
       bandOption = self.frame_2.clicked.get()
      
       if bandOption == "B":
           
           qe.delete(0,tk.END)
           qe.insert(0,22)
       elif bandOption == "V":
           qe.delete(0,tk.END)
           qe.insert(0,33)
        
    
    
class frame(Calculator):
#                       Creates a frame class for automatic frame generation
#                         with entries, labels and/or option menus
# 1. name : frame name
# 2. label_default_values: name of labels
# 3. entry_default_values: default values in entries
# 4. entry_width: the entries dimensions
# 5. I: number of labels and entries
# 6. grid_row: frame grid row placement
# 7. grid_column: frame grid column placement
# 8. option_menu: true or false if user wants a option list or not
# 9. option_list_values: list for option menu
# 10. option_label: name for option menu label
# 11. ipax, ipady: padding
# 12. comand: comand for option list

    def __init__(self, name, label_default_values, entry_default_values, entry_width, I, grid_row, grid_column, 
                 option_menu1, option_list_values, option_label, 
                 option_menu2, option2_list_values,option_label2,
                 ipad_x, ipad_y
                ):
        
        self.name = name
        self.label_default_values = label_default_values
        self.entry_default_values = entry_default_values
        self.I = I
        self.grid_row = grid_row
        self.grid_column = grid_column
        self.dropMenu_options = option_list_values
        self.label = option_label
        self.entry_width = entry_width
        self.dropMenu_options2 = option2_list_values
        self.option_label2 = option_label2
        self.ipad_x = ipad_x
        self.ipad_y = ipad_y
        

        frame = tk.LabelFrame(window, text = name, highlightbackground='grey', highlightthickness=1)
        frame.grid(row=self.grid_row, column=self.grid_column, padx=5, pady=5, ipadx=ipad_x, ipady=ipad_y)
       
        if option_menu1 == "option_menu1_yes":
         
            
            self.clicked = tk.StringVar()
            self.clicked.set(self.dropMenu_options[0])
            self.drop = tk.OptionMenu(frame, self.clicked, *self.dropMenu_options, command = self.add)
            self.drop.grid(row=5, column=1, sticky="ew")
            label = tk.Label(frame, text = option_label, highlightbackground='grey', highlightthickness=1)
            label.grid(row = 5, column = 0, sticky = "w")
        
        if option_menu2 == "option_menu2_yes":
            self.clicked2 = tk.StringVar()
            self.clicked2.set(self.dropMenu_options2[0])
            self.drop2 = tk.OptionMenu(frame, self.clicked2, *self.dropMenu_options2)
            self.drop2.grid(row=6, column=1, sticky="ew")
            label = tk.Label(frame, text = option_label2, highlightbackground='grey', highlightthickness=1)
            label.grid(row = 6, column = 0, sticky = "w")
            
        
        self.entry ={}

        for i in range(0, self.I):
         
            label = tk.Label(frame, text = self.label_default_values[i], justify = "left")
            label.grid(row=i, column=0, sticky = "w")
            
            self.entry[i] = tk.Entry(frame, textvariable = float(self.entry_default_values[i]), width=self.entry_width)
            self.entry[i].grid(row=i, column=1, sticky = "e")
            self.entry[i].delete(0, tk.END)
            self.entry[i].insert(0, self.entry_default_values[i])  

c=Calculator(window)
window.mainloop()

CodePudding user response:

There are 2 problems:

  • The first one is that you mentioned and to fix it:
    rename def add(self) to def add(self, e) and rename add() to add(None). Then change lambda event: self.add to self.add
  • The second one is:
    AttributeError: 'frame' object has no attribute 'frame_camera' but is not question related

CodePudding user response:

It works if I define add(event) outside classes.

def add(event):
   
   qe = c.frame_1.entry[1]
   bandOption = c.frame_2.clicked.get()
  
   if bandOption == "B":
       qe.delete(0,tk.END)
       qe.insert(0,22)
   elif bandOption == "V":
       qe.delete(0,tk.END)
       qe.insert(0,33)

And this in the frame class:

self.drop = tk.OptionMenu(frame, self.clicked, *self.dropMenu_options, command = lambda event:add(event))
  •  Tags:  
  • Related