Tkinter error - Tuple index out of range - python

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.

Related

Calling methods from outside a class in Python - Tkinter events

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.

How Do I assign a function to a button in Python/TKinter?

I am fairly new to TKinter and have been trying to convert my normal Python code into a GUI (TKinter Code)! I have been working on this code and so far, I have got the basic layout made but I am having problems coding buttons and using entries. You will most likely find a lot of errors in my code so be warned! :D
I have got an entry at the top of the window and I want the user to input a number into the entry and then I want to use the text inputted in the entry in some code (btn1()). I also want the user to press a button and then the button to run some code with labels underneath where the buttons are showing the results of the code (the labels in the btn1() function).
First, I want the user to input a number into the entry. Then, I want the user to click on a button which is underneath the entry. Finally, I want the results of the code behind the button, to be show underneath the buttons (in labels!).
Here is my code:
from tkinter import *
class window_design:
def __init__(self):
root=Tk()
root.title("Bag Weight")
root.geometry("500x700")
root.wm_iconbitmap('favicon.ico')
image=PhotoImage(file="Weight Program.png")
imagelabel=Label(root,image=image)
imagelabel.pack()
weightentrylabel=Label(root,text="Enter Weight!")
weightentrylabel.pack()
self.string=StringVar()
weightentry=Entry(root,textvariable=self.string)
weightentry.pack()
menutext=Label(root,text="What coin are you using?")
menutext.pack(side=LEFT)
values=['1p','2p','5p','10p','20p','50p','£1','£2','Exit']
def btn1(self,btn1code):
p1=3.56
p1should=356
if (self.string.get()) > p1should:
weightdif=(self.string.get())-p1should
coins=weightdif/p1
labeldif=Label(text=weightdif)
labelcoins=Label(text=coins)
elif (self.string.get()) < p1should:
weightdif=p1should-(self.string.get())
coins=weightdif/p1
labeldif=Label(text=weightdif)
labelcoins=Label(text=coins)
button1=Button(root,text="1p",command=btn1)
button1.pack(side=LEFT)
root.mainloop()
window_design()
I am currently getting this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\cjay2\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
TypeError: btn1() missing 2 required positional arguments: 'self' and 'btn1code'
You should use self.btn1 ( btn1 is a class method) in button1=Button(root,text="1p",command=btn1).
btn1() is called with one argument and it needs two arguments, set a default value to btn1code or removeit (if you do not use it).
When you call get() method on StringVar() it will return a string so you need to convert before comparing with integers.
To show result in label use a self.result = StringVar() then call self.result.set(a_string).
Check the following code:
from tkinter import *
class window_design:
def __init__(self):
root=Tk()
root.title("Bag Weight")
#root.geometry("500x700")
root.wm_iconbitmap('favicon.ico')
image=PhotoImage(file="Weight Program.png")
imagelabel=Label(root,image=image)
imagelabel.pack()
weightentrylabel=Label(root,text="Enter Weight!")
weightentrylabel.pack()
self.string=StringVar()
weightentry=Entry(root,textvariable=self.string)
weightentry.pack()
menutext=Label(root,text="What coin are you using?")
#menutext.pack(side=LEFT)
menutext.pack()
values=['1p','2p','5p','10p','20p','50p','£1','£2','Exit']
button1=Button(root,text="1p",command=self.btn1)
#button1.pack(side=LEFT)
button1.pack()
#--------------------------------------------------
self.result=StringVar()
resultlabel=Label(root, textvariable = self.result)
resultlabel.pack()
#--------------------------------------------------
root.mainloop()
#-------------------------------------
def btn1(self):
p1=3.56
p1should=356
if not self.string.get(): return
value = int(self.string.get())
if value > p1should:
weightdif = value - p1should
coins=weightdif/p1
elif value < p1should:
weightdif=p1should - value
coins=weightdif/p1
self.result.set(coins)
#-----------------------------------
window_design()
You defined btn1() as needing an argument besides self, but Tkinter is calling it without one. It looks like you are not even using btn1code, so you can change your function definition to def btn1(self):
you can declare btn1code as member variable,and remove it from your function definition, or if you want call function with arguments from the Button; use lambda function like this :
button1=Button(root,text="1p",command=lambda: btn1(btn1code))

Syntax Error; Python game spits out super method and imports

I made classes for what will basically become a BreakOut game, but I keep getting error messages. The nature of which always seem to surround two things; Class imports and the infamous "super" method. Usually in the form of a syntax error
I had some questions shot down in the past, so I will try to be as clear as I possibly can.
The main code for the game is as such...
import pygame
from Game import *
from Game.Scenes import *
from Game.Shared import *
class BreakOut:
def __init__(self):
self.__lives = 5
self.__score = 0
self.__level = Level(self)
self.__level.load(0)
self.__pad = Pad((0,0), 0)
self.__balls = [Ball((0,0), 0, self)]
pygame.init()
pygame.mixer.init()
pygame.display.set_caption("This is the Title of the Game")
self.__clock= pygame.time.Clock()
self.screen = pygame.display.set_mode(GameConstants.SCREEN_SIZE, pygame.DOUBLEBUF, 32)
pygame.mouse.set_visible(0)
self.__scenes = (
PlayingGameScene(self),
GameOver(self),
HighScoreScene(self),
MenuScene(self)
)
self.__currentScene = 0
self.__sounds = ()
def start(self):
while 1:
self.__clock.tick(100)
self.screen.fill((0,0,0))
currentScene = self.__scenes[self.__currentScene]
currentScene.handleEvents(pygame.event.get())
currentScene.render()
pygame.display.update()
def changeScene(self, scene):
pass
def getLevel(self):
pass
def getScore(self):
pass
def increaseScore(self, score):
pass
def getLives(self):
pass
def getBalls(self):
pass
def getPad(self):
pass
def playSound(self, soundClip):
pass
def reduceLives(self):
pass
def increaseLives(self):
pass
def reset (self):
pass
BreakOut().start()
At this stage, its only supposed to return a black screen, but instead it keeps giving me a error message with this traceback:
Traceback (most recent call last):
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 3, in <module>
from Game import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/__init__.py", line 9, in <module>
from Game.BreakOut import BreakOut
File "/Users/Ryan/PycharmProjects/Demo 1/Game/BreakOut.py", line 4, in <module>
from Game.Scenes import *
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/__init__.py", line 3, in <module>
from Game.Scenes.HighScoreScene import HighScoreScene
File "/Users/Ryan/PycharmProjects/Demo 1/Game/Scenes/HighScoreScene.py", line 7
SyntaxError: invalid syntax
The bottom one connects to another class of code that looks like this:
from Game.Scenes.Scene import Scene
class HighScoreScene(Scene):
def __init__(self, game):
super(HighScoreScene, self.__init__(game)
PyCharm seems to highlight "super" and tells me "Old-style class contains call for super method" I don't know if that's important or not, but its something I've noticed consistently throughout the code.
I'm pretty sure its a simple mistake. Might be a typo, but I can't pinpoint it for the life of me. Please help!
super(HighScoreScene, self.__init__(game) # <- missing paren
It should be super(HighScoreScene, self).__init__(game)
And use object class BreakOut(object) if you want to use super.
New-style and classic classes
Your class Breakout line is not in line with the rest of your program (ahead by one space). If you backspace that line by one, everything should be fine (including #Padraic Cunningham 's answer).

Global variable is not defined

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.

maximum recursion depth exceeded while calling a python object

My aim is to instantiate a class called arrow, so I can have more arrows then just 1. I wanted to start with the coordinates 200, 200 and want to increase x by 15 per every 100 milliseconds. But when I try to execute this code it gives me following error:
File "game.py", line 25, in moveArrow
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord)) #repeat, changing x
File "game.py", line 24, in moveArrow
arrow.place(x = xCoord, y = yCoord) #replace with new x,y
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1860, in place_configure
+ self._options(cnf, kw))
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1055, in _options
elif isinstance(v, (tuple, list)):
RuntimeError: maximum recursion depth exceeded while calling a Python object
The "File "game.py", line 25, in move Arrow self.after(100, self.moveArrow(arrow, xCoord+15, yCoord)) #repeat, changing x" gets repeated very often as well.
from Tkinter import *
from random import randint
from PIL import ImageTk, Image
class App(Frame):
def __init__(self, master=None):
Frame.__init__(self, master, height=400, width=400)
self.master = master
self.master.bind('<Shift_L>', self.createArrow)
def createArrow(self, event):
self.arrow = Arrow(self)
self.arrow.moveArrow(self.arrow, 200, 200)
class Arrow(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.arrowImage = ImageTk.PhotoImage(Image.open("arrow.gif"))
Label(self, image=self.arrowImage).pack()
def moveArrow(self, arrow, xCoord, yCoord):
arrow.place_forget()
arrow.place(x = xCoord, y = yCoord)
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))
root = Tk()
root.title("Mein erstes Spiel")
app = App(master=root).pack()
root.mainloop()
The other answers are correct about the source of the problem being this line:
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))
But the answer is Tkinter specific:
Take a look at the docs for the after method to see how to properly implement this method. Calling it like a normal function call will do just that and throw your program into an infinite loop when the control flow reaches that function call. When you use after, you have two options:
Passing the time arg, then the callback, then the callback args:
self.after(100, self.moveArrow, arrow, xCoord+15, yCoord)
Or, using a lambda expression to hold the function call:
self.after(100, lambda: self.moveArrow(arrow, xCoord+15, yCoord))
You are calling self.moveArrow(arrow, xCoord+15, yCoord) inside moveArrow() method.
so you have an endless recursion with no break at any stage.
if you want to understand how to build python recursion method you can read here
If you want to create some simple moving effect, then just do it on a loop lets say that you get moving the arrow at x + 200 and y + 200 generate a simple for loop and move the arrow with a delay.
pseudo code example:
def moveArrow(....)
loop:
x += 10
y += 10
change_arrow_place(...)
Line which create problem is
self.after(100, self.moveArrow(arrow, xCoord+15, yCoord))x
Because moveArrow has no break condition. When ever we use recursion in programming language, recursion need break condition from where it will not call further same function.
for example : prime number in recursion
int isPrime(int num,int i){
if(i==1){
return 1;
}else{
if(num%i==0)
return 0;
else
isPrime(num,i-1);
}
}
in above code break conditions are if (i==1) and if(num%i==0) in these 2 condition it will not call isPrime function and recursion will terminate there.
Please add break condition and run again.

Categories

Resources