I want to call a method in another class and make changes to the parent class when the button is clicked in Python. To explain; With Tkinter visual programming, I click the button to change the main window and I can not change the properties in the main window with another class method.
I get the error message below.
Exception in Tkinter callback Traceback (most recent call last):
File "/usr/lib/python3.5/tkinter/_ init _.py", line 1553, in _
call _
return self.func(*args) TypeError: buton_goster() missing 1 required positional argument: 'event'
class Butonol(object): #Button class
def __init__(self):
...
def buton_goster(self, event ): # Properties kisminda ozellik gosterir
Test.countshow = Test.countshow + 1;
if(Test.countshow >1):
Test.props0.pack_forget()
Test.props.pack_forget()
...
And here is the Test Class
class Test(Frame):
countshow = 0
...
def new_Button(self):
self.nesne = Butonol()
self.but= Button(self.mainFrame,text = self.nesne.text)
self.but.bind('<Button-1>',Butonol.buton_goster)
self.but.bind('B1-Motion>',self.label_tasi)
self.but.pack(side = LEFT,anchor = N)
Butonol.butonsay = Butonol.butonsay + 1
Butonol.butonliste.append(self.but)
The error is correct,
When you do you bind, you do not pass on the event, you simply add the function pointer.
If the buton_goster does not need "event" you should remove it or you should provide event as input when calling the function.
Related
A Tkinter GUI where a bunch of 'visual effect' classes call a control panel generator
which produces a panel made up of widgets associated with the effect's parameters to modify the image on screen interactively.
tkvars = [tk.IntVar, tk.DoubleVar, tk.BooleanVar, tk.StringVar] # Available Tk variable types
Each variable-to-be goes through this loop to get the correct type of tk variable
for its intended widget.
val = the value I want to set the variable to. The type of Tk variable required
for that widget is based on the type of that value.
**if** ftype == 1: ## CHECKBOX
wvar = tkvars[2] # Returns a BooleanVar
wvar.**set**(val)
**return** wvar # Returns a Tk var of the correct type set to the correct value
**elif** ftype == 2: ## RADIO
wvar = tkvars[0] # Returns an IntVar
wvar.set(val)
self._radiovar.**append**(wvar)
**return** wvar # Returns a Tk var of the correct type set to the correct value
**elif** ftype == 3: ## SLIDERS
if **str**(type(val)) in vartype: vix = vartype.**index**(str(type(val)))
# The above line figures which type (int, float) is required
wvar = tkvars[vix]
**print**(">>>>>>>>>>>>>>>SLIDER", tkvars[vix], vix, wvar, val)
wvar.**set**(val)
**return** wvar # Throws an error message:
# ***TypeError: set() missing 1 required positional argument: value*'**
Problem is, the printout reveals that I'm attempting to set a Tk variable of the right type with the correct value, but that I now need two arguments for the Tk.variable**.set()** method.
First time I get that, and I have dozens of effect classes set up and working in the GUI. Here's the full traceback message:
Traceback (most recent call last):
File "C:\Users\miche\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "D:/_DOCS/_CODE/ImProc/__PXL/PXL_5.py", line 10473, in clickend
res = f.dialog()
File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_classesA.py", line 119871, in dialog
ShapesFx.pages
File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 6941, in __init__
super(Dbuilder, self).__init__(parent, fields, caller, pages, isXpand, title)
File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 732, in __init__
self.initial_focus = self.body(body)
File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 7024, in body
wvar = self.getvars(parentframe, fix, item)
File "D:\_DOCS\_CODE\ImProc\__PXL\pxl_dialogs.py", line 7227, in getvars
wvar.set(val)
**TypeError: set() missing 1 required positional argument: 'value'**
Consider this code:
tkvars = [tk.IntVar, tk.DoubleVar, tk.BooleanVar, tk.StringVar]
You are creating a list of classes, not variables.
The reason for the error is that you are calling the method on the class rather than an instance of the class. Like all python classes, when you call the method on an instance python will automatically pass in the value for self. Since you aren't calling the set method on an instance, your val is being passed to the self parameter, and thus there is no argument being passed as the value.
If you wish to put the class of variable in your list (as opposed to instances of the class), you need to instantiate the class before setting the value. For example:
if ftype == 1: ## CHECKBOX
cls = tkvars[2] # returns the variable class
wvar = cls() # instantiates the class
wvar.set(val) # sets the value of the instance
return wvar # returns the instance
Note: you can set the value at the time of instantiation to save one line of code:
wvar = cls(value=val)
If you don't need a new variable instantiated each time this code runs, you can instantiate the classes when you initialize the list:
tkvars = [tk.IntVar(), tk.DoubleVar(), tk.BooleanVar(), tk.StringVar()]
This program is supposed to put a sprite on the canvas for the user to control using the left and right arrow keys, but I keep getting a Tuple index out of range error, and I do not have any tuples in my program. I know that I properly imported the picture, so its probably something to do with the key pressing event.
#4/22/15
#Test game, user controlled sprite
import random
from Tkinter import *
import Tkinter
from PIL import Image, ImageTk
root = Tk()
root.geometry('700x600')
canvas = Canvas(root,width=700,height=600,bg='white')
canvas.place(x=0,y=0)
class Character_sprite(object):
'''Creates the users sprite and handles the events'''
def __init__(self):
self.im = Image.open('grey_mario_mushroom_sprite.png')
self.tkimage = ImageTk.PhotoImage(self.im)
self.char_sprite = canvas.create_image(image=self.tkimage)
def moveLeft(event):
'''Handles the left arrow key press event, moves char_sprite to the left'''
canvas.move(self.char_sprite,-20,0)
canvas.update()
def moveRight(event):
'''Handles the right arrow key press event, moves the char_sprite to the right'''
canvas.move(self.char_sprite,20,0)
canvas.update()
root.bind('<Left>', Character_sprite.moveLeft)
root.bind('<Right>', Character_sprite.moveRight)
Character_sprite()
root.mainloop()
This is the error:
Traceback (most recent call last):
File "C:\Users\Calvin\Documents\Python Programs\Test_game_example.py", line 57, in <module>
Character_sprite()
File "C:\Users\Calvin\Documents\Python Programs\Test_game_example.py", line 36, in __init__
self.char_sprite = canvas.create_image(image=self.tkimage)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2310, in create_image
return self._create('image', args, kw)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2294, in _create
cnf = args[-1]
IndexError: tuple index out of range
Please help!
The problem is that create_image requires a position. Like this:
self.char_sprite = canvas.create_image((0, 0), image=self.tkimage)
If Tkinter had been defined in a more friendly way, you'd get a friendlier error message:
>>> def create_image(position, **options):
... pass
>>> create_image(image=0)
TypeError: create_image() takes exactly 1 argument (0 given)
Unfortunately, Tkinter is often a bit complicated under the covers, so it's defined more like this:
>>> def create_image(*args, **options):
... position = args[-1]
... pass
So, you get a less useful error message. The *args ends up as an empty tuple, so that position = args[-1] raises an IndexError. And of course the variable isn't even called position, but cnf, which doesn't help you understand the problem.
But it's the same problem. You forgot to pass the position argument.
I'm trying but it's not working. I have the following code line:
class Run:
def Method(self, choice):
print "%sZip :\t%s%s\n".decode('utf-8') % (Basic_Green, White, choice.start().LoadJson['zip'])
And this is variable, and is within another class, and another function:
class Host_Method:
def start(self):
My_API = requests.get("http://ip-api.com/json/%s" % socket.gethostbyname(sys.argv[2]))
LoadJson = json.loads(My_API.content)
The error:
Traceback (most recent call last):
File "InfoIP.py", line 78, in <module>
elif sys.argv[1] == "-h": Run().Method(Host_Method())
File "/Pentest/InfoIP2/Libraries/InfoIP_Functions.py", line 159, in Method
print "%sZip :\t%s%s\n".decode('utf-8') % (Basic_Green, White, choice.LoadJson['zip'])
AttributeError: Host_Method instance has no attribute 'LoadJson'
You probably want them to be stored in an instance variable (self....). And you probably want your start to be an __init__ method. Your corrected class could look like:
class HostMethod:
def start(self):
self.my_API = requests.get("http://ip-api.com/json/{0}".format(socket.gethostbyname(sys.argv[2])))
self.load_json = json.loads(self.my_API.content)
Then, you could do:
class Run:
def Method(self, choice):
print "{0}Zip :\t{1}{2}\n".decode('utf-8').format(Basic_Green, White, choice.load_json['zip'])
a = Run()
a.method(HostMethod())
See also:
https://docs.python.org/3.4/tutorial/classes.html
I'm sending a variable value from programa1 for a new object using :
def send_price(self):
self.pricesend = float(self.text1.get()) #this take a value from a tkinker.Entry
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
the object "objetoprograma1" return a new value using:
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
now I want to update the value in the principal1 tkinter.Entry called self.text1:
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work.. this don't update or change the value in the tkinter.Entry
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
I have the following exception:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1482, in __call__
return self.func(*args)
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 38, in send_price
objetoprograma1.Object(self.pricesend)
File "B:\MAESTRIA\PYTHON\trabajos\hello\objetoprograma1.py", line 19, in __init__
programa1.Aplication.recibe_newprice(self, float(self.new_price))
File "B:\MAESTRIA\PYTHON\trabajos\hello\programa1.py", line 51, in recibe_newprice
self.text1.delete(self.my_main, len(self.text1.get()))
AttributeError: 'Object' object has no attribute 'text1'
the full programa1.py
# -*- coding: latin-1 -*-
import tkinter
import objetoprograma1
import time
class Aplication():
def __init__(self,my_main):
self.my_main = my_main
self.variables()
self.GUI()
def variables (self):
self.price = None
self.list = []
def GUI(self):
self.text1 = tkinter.Entry()
self.text1.insert(0, "1000")
self.text1.grid(column = 0, row = 0)
self.boton1 = tkinter.Button(self.my_main, text = "sendprice", command = self.send_price )
self.boton1.grid(column=1, row = 0)
def send_price(self):
self.pricesend = float(self.text1.get())
print(self.pricesend)
objetoprograma1.Object(self.pricesend)
def recibe_newprice(self, new_price):
self.new_price = new_price
print("price new recibe" , self.new_price)
## this don't work
self.text1.delete(0, len(self.text1.get()))
self.text1.insert(self.my_main, str(self.new_price))
if __name__ == "__main__":
root = tkinter.Tk()
#root.geometry("800x500+0+0")
root.title("titulo")
app = Aplication(my_main=root)
root.mainloop()
and objetoprograma1.py
# -*- coding: latin-1 -*-
import programa1
import tkinter
import time
class Object():
def __init__(self, price):
self.price_recibe = float(price)
print(self.price_recibe)
self.new_price = self.price_recibe + 10
print(self.new_price)
programa1.Aplication.recibe_newprice(self, float(self.new_price))
Look at your Object class and look at the exception message. You are calling the recibe_newprice method, but passing it the Object instance (Object has no text1 attribute). The recibe_newprice is written for the Aplication class and as such expects self to be an instance of the Aplication class. You seem to be mixing up what classes are for or how the self argument works.
My first tip is to name things with more descriptive names. Names like Object, Application, and Program1 don't tell the reader anything about what the purpose of those objects are.
Second, do you know the difference between classes and functions? Maybe this will help. I would code the send_price method this way:
def send_price(self, price_recibe):
pricesend = float(self.text1.get())
print(pricesend)
print(price_recibe)
new_price = price_recibe + 10
print(new_price)
self.recibe_newprice(new_price)
If this doesn't make sense why I'm doing things this way or why this might be considered better/easier than the way you did it then I suggest researching how python classes, attribute assignment, and argument passing works.
I'm trying to read a file with python, by posting the address in input line. In my plan, when I press the button, program will read the file, make all needed work with the text inside the first file, and write the result into a second one:
import Tkinter
class Generator(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent=parent
self.initialize()
def initialize(self):
self.grid()
self.addressLink = Tkinter.StringVar()
self.entry=Tkinter.Entry(self,textvariable=self.addressLink)
self.entry.grid(column=0,row=0,sticky='EW')
self.entry.bind("<Return>", self.OnPressEnter)
self.entry.bind(".", self.OnPressDot) # verify that address was accepted
self.addressLink.set(u"Enter your input file's address here!")
button=Tkinter.Button(self,text=u'Generate the list!',command=self.OnButtonClick)
button.grid(column=1,row=0)
self.labelVariable = Tkinter.StringVar()
label = Tkinter.Label(self, textvariable=self.labelVariable,
anchor="w",fg="white",bg="blue")
label.grid(column=0,row=1,columnspan=2,sticky='EW')
self.labelVariable.set(u"Enter Address !")
self.grid_columnconfigure(0,weight=1)
self.resizable(True,False)
def ProgramBody(readlink):
excelWrite=open('/Users/BUR/Desktop/final_TK.txt','w')
z=0
for index, line in enumerate(readlink, start=0):
keywrds=[]
title=line.split("+")
title=[lines.strip()for lines in title]
print title[0]
print index
header="Title"+"\t"+"Price equal to title:"+"\t"+"keyword1"+"\t"+"keyword2"+" \t"+"keyword3"+"\t"+"keyword4"+"\t"+"keyword5\t"+"Manufacturer Part Number\n"
exclWrt(header)
excelWrite.close()
def FileRead(tsink):
excelRead=open(tsink,'r')
print tsink
ProgramBody(tsink)
def OnButtonClick(self):
link=(self.addressLink.get())
# print link
self.labelVariable.set(link+" (Here is your button press!) ")
FileRead(link)
def OnPressEnter(self,event):
self.labelVariable.set(self.addressLink.get()+" (Here is your address!)")
def OnPressDot(self,event):
self.labelVariable.set(self.addressLink.get()+" (Here is your address!!!)")
if __name__=="__main__":
app=Generator(None)
app.title('Converter')
app.mainloop()
#excelRead=open('/Users/BUR/Desktop/listings/data.txt','r')
def exclWrt(typo):
excelWrite.write(typo)
Program runs, but when I press button it gives me:
> Exception in Tkinter callback Traceback (most recent call last):
> File
> "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py",
> line 1470, in __call__
> return self.func(*args) File "/Users/BUR/Documents/Python/Temp+price+keyw.1", line 114, in
> OnButtonClick
> FileRead(link) NameError: global name 'FileRead' is not defined
What did I miss?
You're using a class. First, you'll have an instance of the class passed to every function. Usually it's named self:
class A:
def something(self, my_arguments)
And, to call something from the class, you do this:
def something_else(self, another_arguments):
self.something(another_arguments)
The first argument will automatically be passed. Also, __init__ is called when you create an instance of your class, so you have no need of a separate initialize function.
I suggest you read more about classes here. This is just a very short solution for your problem.