Can't get tkinter's StringVar's trace method to work - python

Whenever I try to run my code, which looks a bit like this:
from tkinter import OptionMenu, StringVar, Tk
class Foo(OptionMenu):
def __init__(self, master, options):
self.bar = StringVar()
self.bar.set(options[0])
self.bar.trace("w", lambda: self.mouseCallback("foobar"))
super().__init__(master, self.bar, *options)
def mouseCallback(self, baz):
print(baz)
def mainCycle():
while True:
root.update()
if __name__ == "__main__":
opts = ["A", "LONG", "LIST", "OF", "OPTIONS"]
root = Tk()
foobarbaz = Foo(root, opts)
foobarbaz.pack()
mainCycle()
I get the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 3285, in __call__
self.__var.set(self.__value)
File "C:\Program Files\Python35\lib\tkinter\__init__.py", line 260, in set
return self._tk.globalsetvar(self._name, value)
_tkinter.TclError: can't set "PY_VAR0":
And even after a lot of "Stack Overflowing", I still can't get it to work. How can I avoid/fix this error?

The signature of the callback function for StringVar.trace() should be something like def callback(*args), therefore the lambda you use in StringVar.trace() should be changed to:
self.bar.trace("w", lambda *args: self.mouseCallback("foobar"))

Related

Add attribute to Table class from pandastable

I would like to add a new attribute to the class table from the package pandastable by inheritance. I use the following code for this:
import pandas as pd
from pandastable import Table
import tkinter as tk
class MyTable(Table):
def __init__(self, list_items, *args, **kwargs):
self.list_items = list_items
super(MyTable, self).__init__(*args, **kwargs)
top = tk.Tk()
top.geometry("300x300")
df = pd.DataFrame()
df["column1"] = [1,2,3,4,5,6,7,8,9,10,11,12,13,1,1,1,1,1,1,1]
df["column2"] = [1,2,3,4,5,6,7,8,9,10,11,12,13,1,1,1,1,1,1,1]
df["column3"] = [1,2,3,4,5,6,7,8,9,10,11,12,13,1,1,1,1,1,1,1]
df["column4"] = [1,2,3,4,5,6,7,8,9,10,11,12,13,1,1,1,1,1,1,1]
frame = tk.Frame(top)
frame.pack(fill="both", expand=True)
pt = MyTable(frame, dataframe=df)
pt.focus_set()
pt.show()
top.mainloop()
When I run the code, I get following error message:
Traceback (most recent call last):
File "....py", line 47, in <module>
pt = MyTable(frame, dataframe=df)
File "/....py", line 9, in __init__
super(MyTable, self).__init__(*args, **kwargs)
File "...e.py", line 134, in __init__
self.doBindings()
File "....py", line 262, in doBindings
self.parentframe.master.bind_all("<KP_8>", self.handle_arrow_keys)
AttributeError: 'NoneType' object has no attribute 'master'
The error occurs in the package function doBindings. but why does it occur only after I have changed the __init__ function?
First you need to pass the parent option to Table(). Second suggest to use keyword argument list_items instead of positional argument.
class MyTable(Table):
# add parent argument and remove *args
def __init__(self, parent, **kwargs):
# get the keyword argument 'list_items' if provided, otherwise set it to None
self.list_items = kwargs.pop('list_items', None)
# pass required parent argument to Table class
super().__init__(parent, **kwargs)

Kivy Button: on_press function called before its being pressed

Im writing a Sudoku solver UI in Kivy.
I wanted to add a button, which upon being pressed, solves the Grid. The function works, although when I assign it to a button as the on_press function, it somehow runs before the button is pressed. I've tried everything. I get an Assertion Error. When I just use the solve function, it works. Not with the button, though.
Thank you for helping.
This is the __init__ function:
class SudokuGrid(GridLayout):
def __init__(self, **kwargs):
super(SudokuGrid, self).__init__(**kwargs)
self.grid = [[8,7,0, 0,0,0, 0,0,0],
[0,0,0, 9,0,0, 0,0,4],
[0,2,0, 7,0,0, 1,0,5],
[0,0,9, 6,0,0, 0,3,0],
[0,0,0, 0,0,0, 0,0,9],
[0,0,6, 5,4,0, 0,0,0],
[6,9,0, 0,0,0, 7,0,0],
[2,0,0, 0,0,7, 4,0,0],
[0,0,0, 3,0,0, 0,1,0]]
self.add_widget(Button(on_press=self.solve()))
self.cols = 3
self.rows = 4
self.load_grid()
And this my solve function:
def solve(self):
for x in range(9):
for y in range(9):
if self.grid[y][x] == 0:
for n in range(1,10):
if self.possible(y,x,n):
self.grid[y][x] = n
self.solve()
self.grid[y][x] = 0
return
self.load_grid()
print(np.matrix(self.grid))
I know that the function is run, because before the App terminates, I get the output of the solved Grid.
This is the Traceback:
Traceback (most recent call last):
File "C:\Users\victo\Desktop\portfolio\Sudoku\sudoku_app.py", line 217, in <module>
sudoku_game.run()
File "C:\Users\victo\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\app.py", line 829, in run
root = self.build()
File "C:\Users\victo\Desktop\portfolio\Sudoku\sudoku_app.py", line 205, in build
self.sudoku_grid = SudokuGrid()
File "C:\Users\victo\Desktop\portfolio\Sudoku\sudoku_app.py", line 73, in __init__
self.add_widget(Button(on_press=self.solve()))
File "C:\Users\victo\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\behaviors\button.py", line 121, in __init__
super(ButtonBehavior, self).__init__(**kwargs)
File "C:\Users\victo\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\label.py", line 318, in __init__
super(Label, self).__init__(**kwargs)
File "C:\Users\victo\AppData\Local\Programs\Python\Python37-32\lib\site-packages\kivy\uix\widget.py", line 369, in __init__
self.bind(**on_args)
File "kivy\_event.pyx", line 419, in kivy._event.EventDispatcher.bind
AssertionError: None is not callable
Okay so i figured it out. Erik said in his comment:
Try on_press=self.solve in stead of on_press=self.solve()
which worked, although I got another Error. I had one too many positional arguments for solve(). I fixed it by defining my method as:
def solve(self, *args)
Everything works now.

Can't find tkinter AttributeError

I am writing a code for banking system using python and Tkinter. When I run the program I encounter a few errors. Could someone please help me to figure this out. I have done research about it, but can't find a solution to the problem.
Here is the error:
...File "C:\Users\stjur\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 2256, in _setup
self.tk = master.tk
AttributeError: 'function' object has no attribute 'tk'
And here is my code:
from tkinter import *
root=Tk()
root.title('Avis Banking System')
def win1():
global balance
balance=600
global root
global tries
root=Tk()
root.title('Avis banking system')
entry_1Var=StringVar()
entry_2Var=StringVar()
tries=0
tries=0
def CheckPass():
global tries
if (tries<3):
textvalue=entry_1Var.get()
textvalue=entry_2Var.get()
if textvalue!=('John123') and textvalue!=('Secret'):
tries+=1
label3=Label(root,text='Try again')
label.grid(row=3,column=1,sticky=W,padx=7)
else:
win2()
if (tries==3):
label4=Label(root,text='Used all attempts, entry blocked')
label4.grid(row=3,column=1, sticky=W,padx=7)
entry_1Var=StringVar()
entry_2Var=StringVar()
b1=Button(root,text='Login',width=5,command=CheckPass)
b1.grid(row=1,column=10,sticky='e'+'w',padx=7)
b2=Button(root,text='Reset',width=5,)
b2.grid(row=2,column=10,sticky='e'+'w',padx=7)
l1=Label(root,text='Username:').grid(row=1,padx=7,pady=5,sticky='we')
l2=Label(root,text='Password:').grid(row=2,padx=7,pady=5,sticky='we')
e1=Entry(root,width=30,textvariable=entry_1Var)
e1.grid(row=1,column=1,sticky='e'+'w',columnspan=2)
e2=Entry(root,show='*',width=30,textvariable=entry_2Var)
e2.grid(row=2,column=1,sticky='e'+'w',columnspan=2)
logLabel=Label(root,text='Login',font='bold',fg='Grey')
logLabel.grid(row=0,padx=5,pady=5)
check=Checkbutton(root,text='Keep me logged in')
ckeck.grid(row=4,column=1,sticky=W,pady=5)
if (tries==3):
win2
def win2():
#this is the child window of the main window.
win2=Toplevel(root)
win2.minsize(width=400,height=400)
win2.title("Main Menu")
#Label for the the main menu
lb=Label(win2,text='N&E Scotland Bank\nMain Menu:',bg='#e6e6e6',height=6).pack(fill=X)
btn_1=Button(win2,text='Make Deposit',width=15,height=2,command=win3).pack(pady=5)
btn_2=Button(win2,text='Withdrawal',width=15,height=2).pack(pady=5)
btn_3=Button(win2,text='Accounts',width=15,height=2).pack(pady=5)
btn_4=Button(win2,text='Balance',width=15,height=2).pack(pady=5)
btn_5=Button(win2,text='Exit',width=15,height=2).pack(pady=5)
def win3():#new window for the button make depost
win3=Tk()
win3.title('Make Deposit')
win3.minsize(width=400,height=120)
e1=IntVar()
e2=IntVar()
def MakeDeposit():
num2 = e2.get()
balance = int(num2)
num1 = e1.get()
depositAmount = int(num1)
while depositAmount<=0 or depositAmount%10!=0:
errorLabel = Label(win3,text="That was not a valid amount").grid(row=3,columnspan=5)
return#
textLabel = Label(win3,text=("Your new balance is:\n")).grid(row=3,columnspan=5)
newBalanceLabel = Label(win3,text=(balance+depositAmount)).grid(row=4,columnspan=5, pady=7)
l1=Label(win3,text='Deposit Amount:').grid(row=1,padx=7,pady=5,sticky='we')
l2=Label(win3,text='Balance:').grid(row=2,padx=7,pady=5,sticky='e')
b1=Butto(win3,text='Calculate',width=8,height=3,command=MakeDeposit).grid(row=1,column=10,sticky='e'+'w',padx=7,rowspan=2)
e1=Entry(win3,width=40)
e1.grid(row=1,column=1,sticky='e'+'w',columnspan=3)
e2=Entry(win3,width=40)
e2.grid(row=2,column=1,sticky='e'+'w',columnspan=3)
logLabel=Label(root,text='DEPOSIT',font='bold',fg='Grey').grid(row=0,padx=5,pady=5)
root.mainloop()
I can explain the error message. After fixing the formatting errors in my local copy, I got this:
Traceback (most recent call last):
File "F:\Python\mypy\tem.py", line 84, in <module>
l1=Label(win3,text='Deposit Amount:').grid(row=1,padx=7,pady=5,sticky='we')
File "C:\Programs\Python36\lib\tkinter\__init__.py", line 2760, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Programs\Python36\lib\tkinter\__init__.py", line 2286, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Programs\Python36\lib\tkinter\__init__.py", line 2256, in _setup
self.tk = master.tk
AttributeError: 'function' object has no attribute 'tk'
The first, parent argument for any Widget creation call must be a widget. In
l1=Label(win3, ...
you passed the win3 function, which does not have a tk attribute.
For the future, please read about MCVEs.

Python Tkinter : AttributeError: Button instance has no __call__ method

I don't know why this is giving me an attribute error. I want my blah() function to shuffle the cards. I'm calling the builtin function shuffle() from random.
Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1489, in __call__
return self.func(*args)
File "gui1.py", line 105, in blah
shuffle(cards)
AttributeError: Button instance has no __call__ method
Here's the code snippet:
def blah():
global card_count
global path
shuffle(cards)
card_count = 0
path = generate_paths(cards)
print "Cards Shuffled"
shuffle = Button(frame_buttons, text = "SHUFFLE",height = 2, width = 10,command =blah)
shuffle.grid(row = 2 , padx = 40, pady = 40)
shuffle is the name of the function in random. However, it's also the name of the Button. Change the Button's name to something like shuffle_button and you should be fine.

Add parameter to __init__ in function

Here is the original main.py code
kwargs = {
"ffmpeg": args.ffmpeg,
"rtmpdump": args.rtmpdump,
"swfrender": args.swfrender,
}
with presentation.Downloader(pres, **kwargs) as builder:
that initializes this Downloader class
class Downloader(object):
def __init__(self, presentation, overwrite="-n", ffmpeg="ffmpeg", rtmpdump="rtmpdump", swfrender="swfrender"):
self.presentation = presentation
self.ffmpeg = ffmpeg
self.rtmpdump = rtmpdump
self.swfrender = swfrender
When I add an extra argument overwrite
kwargs = {
"ffmpeg": args.ffmpeg,
"rtmpdump": args.rtmpdump,
"swfrender": args.swfrender,
"overwrite": "-y" if args.overwrite else "-n",
}
with presentation.Downloader(pres, **kwargs) as builder:
class Downloader(object):
def __init__(self, presentation, overwrite="-n", ffmpeg="ffmpeg", rtmpdump="rtmpdump", swfrender="swfrender", overwrite="-n"):
self.presentation = presentation
self.ffmpeg = ffmpeg
self.rtmpdump = rtmpdump
self.swfrender = swfrender
self.overwrite = overwrite
python produces this error
Traceback (most recent call last):
File "infoqscraper/main.py", line 374, in <module>
sys.exit(main())
File "infoqscraper/main.py", line 369, in main
module.main(infoq_client, args.module_args)
File "infoqscraper/main.py", line 191, in main
return command.main(infoq_client, args.command_args)
File "infoqscraper/main.py", line 307, in main
with presentation.Downloader(pres, **kwargs) as builder:
TypeError: __init__() got an unexpected keyword argument 'overwrite'
How do I correctly add an argument?

Categories