0

My aim is to load a new "arrow" image every time the user presses the shift button. I thought, that I could make a class for the arrow so I can create a new instance for them where each instance has their own coordinates and so on. But obviously I did that wrong. I tried to make a list for the instances so I can iterate of it and then use the moveArrow method in each instance. I just got 5 entries because I want a limit of 5 arrows at the time. I hope this code doesn't give you eyecancer or something like that :P I am a newb and I am sorry, if the code is really bad or the approach on how to handle my problem. Thank you for your help :)

#!/usr/bin/python

from Tkinter import *
from PIL import ImageTk, Image


class frameApp(Frame):
        def __init__(self, master=None):
                Frame.__init__(self, master, height = 400, width = 400)
                self.charImg = ImageTk.PhotoImage(Image.open("Archer.gif"))
                self.arrowImage = ImageTk.PhotoImage(Image.open("arrow.gif"))
                self.charLabel = Label(self, image = self.charImg) #Loading character label
                self.charLabel.pack()
                self.arrow = Label(self, image = self.arrowImage)
                self.arrow.pack()
                self.shift = False
                self.down = False
                self.right = False
                self.left = False
                self.up = False
                self.x_coord = 200
                self.y_coord = 200
                self.pack_propagate(0)
                self.pack()
                self.arrowList = ["Inst1", "Inst2", "Inst3", "Inst4", "Inst5"]
                self.counter = -1
        def moveableImage(self):
                self.charLabel.place(y=self.y_coord, x=self.x_coord)
        def createArrow(self):
                self.arrowList[counter] = arrow()
        def moveArrow(self):
                for arrowList in self.arrowList:
                        arrowList.moveArrow

        def keyPressed(self, event):
                if event.keysym == 'Down':
                        self.down = True
                elif event.keysym == 'Right':
                        self.right = True
                elif event.keysym == 'Left':
                        self.left = True
                elif event.keysym == 'Up':
                        self.up = True
                elif event.keysym == 'Shift_L':
                        self.shift = True
        def keyReleased(self, event):
                if event.keysym == 'Down':
                        self.down = False
                elif event.keysym == 'Right':
                        self.right = False
                elif event.keysym == 'Left':
                        self.left = False
                elif event.keysym == 'Up':
                        self.up = False
                elif event.keysym == 'Shift_L':
                        self.shift = False
        def task(self):
                if self.down and self.y_coord < 360:
                        self.y_coord = self.y_coord + 10
                elif self.right and self.x_coord < 370:
                        self.x_coord = self.x_coord + 10
                elif self.left and self.x_coord > 10:
                        self.x_coord = self.x_coord - 10
                elif self.up and self.y_coord > 10:
                        self.y_coord = self.y_coord - 10
                elif self.shift:
                        self.counter += 1
                        self.createArrow()
                root.after(20,self.task)
                root.after(20,self.moveArrow)
                self.moveableImage()

class arrow(object):
        def __init__(self):
                self.x_coordArrow = app.x_coord
                self.y_coordArrow = app.y_coord
        def moveArrow(self):
                self.x_coordArrow = self.x_coordArrow + 20

root = Tk()
root.title("Frametitel")
app = frameApp(master=root)
root.bind_all('<Key>', app.keyPressed)
root.bind_all('<KeyRelease>', app.keyReleased)
root.after(20, app.task)
app.mainloop()

1 Answer 1

1

You have several options to handle this. Making a new class to call up multiple instances of arrow() is probably the way to go.

I'd make a class for the application window, which you have, but strip all the unnecessary stuff from it that should be in the Arrow class. Then, make the Arrow class a subclass of a Tkinter widget, like a Frame, and have it handle its methods.

Here's a very simplified version of this:

from Tkinter import *
from random import randint

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):
        #this is the only arrow method in this class. It waits for the Shift event,
        #then makes a new instance of Arrow and calls Arrow's method to get it moving
        self.arrow = Arrow(self)
        self.arrow.moveArrow(self.arrow, randint(0,400), randint(0,400))

class Arrow(Frame):
    def __init__(self, master):
        Frame.__init__(self, master)    #This makes the frame,
        Label(self, text='===>').pack() #and puts a Label (the graphic) inside it

    def moveArrow(self, arrow, xCoord, yCoord):
        #the move arrow method - arguments are the arrow instance and the x,y coords
        arrow.place_forget()            #un-place the instance
        arrow.place(x=xCoord, y=yCoord) #replace with new x,y
        self.after(500, lambda: self.moveArrow(arrow, xCoord+1, yCoord)) #repeat, changing x

root = Tk()
app = App(root).pack()
root.mainloop()
Sign up to request clarification or add additional context in comments.

2 Comments

Why does your moveArrow method not give out a maximum recursion error ? You are calling self.moveArrow(arrow, xCoord+15, yCoord) inside moveArrow() method. Shouldn't you have an endless recursion with no break at any stage ?
Take a look at my answer on your other question dealing with this. You're calling self.after in a way that breaks the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.