'Tkinter Combobox current function not working

Hey there i've spent the last few hours diving through tkinters and my codes dict, I just can't seem to figure out why. I have a combobox that has 10 values loaded into it from a module called brownie. When the textvariable=account_index_val in the combobox gets updated I want to get the index of that option in the combobox list. So that I can use that index to get information from the accounts array from brownie.

I was able to get it to return the string value, essentially the account in a format like this '0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1', but I would much prefer to get it's index. I read up that the current function in the combobox widget would do that. But I get this returned when I try to print it.

anthony@ubuntu-machine:~/python$ brownie console                                                                                     │d
Brownie v1.18.1 - Python development framework for Ethereum                                                                          │(1) 0x6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a
                                                                                                                                     │1
No project was loaded.                                                                                                               │(2) 0x6370fd033278c143179d81c5526140625662b8daa446c22ee2d73db3707e620
Attached to local RPC client listening at '127.0.0.1:8545'...                                                                        │c
Brownie environment is ready.                                                                                                        │(3) 0x646f1ce2fdad0e6deeeb5c7e8e5543bdde65e86029e2fd9fc169899c440a791
>>> import UserInterface                                                                                                             │3
>>> ui = UserInterface.UserInterface()                                                                                               │(4) 0xadd53f9a7e588d003326d1cbf9e4a43c061aadd9bc938c843a79e7b4fd2ad74
-1                                                                                                                                   │3
>>> ui.account_index_val.get()                                                                                                       │(5) 0x395df67f0c2d2d9fe1ad08d1bc8b6627011959b79c53d7dd6a3536a33ab8a4f
'Account'                                                                                                                            │d
>>> ui.ether_account_val_chooser.current                                                                                             │(6) 0xe485d098507f54e7733a205420dfddbe58db035fa577fc294ebd14db90767a5
<bound method Combobox.current of <tkinter.ttk.Combobox object .!frame2.!combobox>>                                                  │2
>>> ui.ether_account_val_chooser.current()                                                                                           │(7) 0xa453611d9419d0e56f499079478fd72c37b251a94bfde4d19872c44cf65386e
-1                                                                                                                                   │3
>>> ui.mainloop()

Here Everything Works, my Window shows up and i can select accounts, every account i select just outputs this. I'm assuming because of the last line of my code.

Exception in Tkinter callback                                                                                                        │4
Traceback (most recent call last):                                                                                                   │(9) 0xb0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c377
  File "/usr/lib/python3.8/tkinter/__init__.py", line 1892, in __call__                                                              │3
    return self.func(*args)                                                                                                          │
TypeError: 'NoneType' object is not callable                                                                                         │HD Wallet
Exception in Tkinter callback                                                                                                        │==================
Traceback (most recent call last):                                                                                                   │Mnemonic:      myth like bonus scare over problem client lizard pione
  File "/usr/lib/python3.8/tkinter/__init__.py", line 1892, in __call__                                                              │er submit female collect
    return self.func(*args)                                                                                                          │Base HD Path:  m/44'/60'/0'/0/{account_index}
TypeError: 'NoneType' object is not callable                                                                                         │
>>>  

Here is my code:

#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
from brownie import *

class UserInterface(tk.Tk):

    ui_title_text = None
    eth_accounts = []
    for account in range(len(accounts)):
        eth_accounts.append(getattr(accounts[account], 'address'))

    account_index_val = -1
    upper_frame_hex = '#033b47'
    middle_frame_hex = '#075f73'
    bottom_frame_hex = '#3b4e52'
    ui_font = 'DejaVu Sans Mono'

    def __init__(self):
        super().__init__()
        self.update()

    def update(self):
        self.title("Camel Coin")
        self.geometry("600x500")
        self.resizable(0, 0)

        self.ui_title_text = tk.StringVar(value="Camel Coin Wallet")
        self.account_index_val = tk.StringVar(self, "Account")

        # Title Frame
        upper_frame = tk.Frame(master=self, height=100, width=500, bg=self.upper_frame_hex)
        upper_frame.pack(fill='both')
        upper_frame.pack_propagate(False)

        # Ethereum Account Frame
        middle_frame = tk.Frame(master=self, height=100, width=500, bg=self.middle_frame_hex)
        middle_frame.pack(fill='both')
        middle_frame.grid_propagate(False)

        # Camel Coin Frame
        bottom_frame = tk.Frame(master=self, height=300, width=500, bg=self.bottom_frame_hex)
        bottom_frame.pack(fill='both')
        bottom_frame.grid_propagate(False)

        # In Title Frame
        ui_title_label = tk.Label(master=upper_frame, textvariable=self.ui_title_text, fg='white', bg=self.upper_frame_hex, font=(self.ui_font, 25))
        ui_title_label.pack(side='top', pady=25)

        # In Ethereum Account Frame
        ether_account_label = tk.Label(master=middle_frame, text=("Ethereum Account: "), fg="white", bg=self.middle_frame_hex, font=(self.ui_font, 10))
        ether_account_label.grid(row=0, column=0, padx=3, pady=5)

        self.ether_account_val_chooser = ttk.Combobox(master=middle_frame, values=self.eth_accounts, textvariable=self.account_index_val)
        self.ether_account_val_chooser.grid(row=0, column=1, padx=0, pady=5, sticky='w')

        self.account_index_val.trace("w", print(self.ether_account_val_chooser.current()))

Interestingly, this function works on startup as it prints "-1" the default for the combobox.



Solution 1:[1]

trace (similar to command=, bind(), after() in Tkinter) needs function's name without () (so called "callback") and later it will use () to run it.

So you should create function with print(...) and use only name of this function in trace

def show():
    print(self.ether_account_val_chooser.current())

self.account_index_val.trace("w", show)  # without `()

or you can use lambda for this

self.account_index_val.trace("w", lambda:print(self.ether_account_val_chooser.current())). 

At this moment your code works like

result = print(...) 

trace("w", result)

so it runs print() at start (and you see -1) and it assigns to result value returned from print(). Because print() returns None so finally you have trace("w", None)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 furas