0

I have a statement inside a while statement that is supposed to draw an image onto the canvas but it doesn't happen and I don't know why as it doesn't show any errors.

def buttonclick_gamescreen(event):
    global scorecounter
    global pressed
    global randomimage
    global images
    pressed = ""

    if event.x >853 and event.x <957 and event.y > 8 and event.y < 56 : pressed = 7 
    if event.x >666 and event.x <947 and event.y > 491 and event.y < 534 : pressed = 8
    while pressed == 8 :
        entryx = e1.get()
        entryy = e2.get()
        answerx = answerlistx[randomimage]
        answery = answerlisty[randomimage]
        print("The answer to X is", answerx, "You entered", entryx,"The answer to Y is", answery, "You entered ", entryy)
        if entryx == answerx and entryy == answery:
            print("correct")
            canvas.delete(images)
            randomimage = random.randrange(0,49+1)
            scorecounter = scorecounter + 1
            print("You score is now", scorecounter, "New random number is", randomimage)
            game = PhotoImage(file=imagelist[randomimage])
            images = canvas.create_image(30, 65, image = game, anchor = NW)
            e1.delete(0, END)   
            e2.delete(0, END)
            pressed = ''
        else:
            print("incorrect")
            e1.delete(0, END)   
            e2.delete(0, END)
            pressed = ''

The line images = canvas.create_image(30, 65, image = game, anchor = NW) should work as it worked in another case for me.

Here's a link to the rest of the code since I don't want to make this question too long and messy, which shows where the canvas is drawn. http://pastebin.com/RxmPDUAD From my understanding right now I'll have to create a class and call the functions from there for this to work? EDIT: Having trouble still as I've tried using global variables and classes with no luck.

It's not a problem with the random number as I printed it just before the line the image is supposed to print from just incase it didn't work but it does. What am I doing wrong?

ThatsNotMyName
  • 572
  • 2
  • 8
  • 24
  • Are you entering the mainloop? Nothing tk-wise will happen until you do. All tasks are essentially queued up, the mainloop will run through the queue of tasks and perform any actions, process events etc. – GP89 Jul 21 '13 at 09:22
  • I'm not entirely sure what that means, but I'm going to guess it's not, so I'll have to go look up that, thanks for the comment. – ThatsNotMyName Jul 21 '13 at 09:41
  • I mean are you calling `canvas.mainloop()` somewhere? (you haven't in the code you provided, but I think that's not all of the code as there are symbols used in there which aren't defined.) – GP89 Jul 21 '13 at 09:56
  • @GP89 It's in the very last line of the second code block, but you are right: The code is not complete, and thus hard to reproduce the problem. Where and how is the canvas created? – tobias_k Jul 21 '13 at 10:04
  • @tobias_k the second code block is an example he says works, though - the code that doesn't work is the first block. – GP89 Jul 21 '13 at 15:24
  • @GP89 Ah, you are right, didn't see this. I guess then that the `mainloop()` at the end prevents the method from ending, and thus the `PhotoImage` is not garbage collected in this case, at least not until the frame is disposed of anyway. Also, since the first code block is some event handling code, I am pretty sure that the frame is already visible (i.e., mainloop is running) when it is executed. – tobias_k Jul 21 '13 at 21:11
  • 1
    It is highly unusual to have to compare the coordinates of the event to some magic numbers. Are you aware that you're able to create events that only fire if someone clicks on a specific button or canvas item so that you don't have to guess which widget was clicked on? – Bryan Oakley Jul 23 '13 at 02:18

1 Answers1

3

Without having actually tested your code, I'm pretty sure the problem is that your PhotoImage objects are being garbage-collected when you exit the method. For some weird reason, just passing them to canvas.create_image won't prevent this. Try to make them global:

global game
game = PhotoImage(file=imagelist[randomimage])
images = canvas.create_image(30, 65, image = game, anchor = NW)

Also see this, this and this related questions/answers.

Some more pointers:

  • conditions like event.x >853 and event.x <957 can be written as 853 < event.x < 957
  • you can define your imagelist as ["%d.gif" % (i+1) for i in range(50)]
  • the after method takes a time in milliseconds, so I guess this should be after(1000, ...)
  • in it's current state, the while pressed == 8: loop seems not to make much sense, since pressed is set to '' after one iteration anyway
  • finally, I'd recommend defining a custom class GameFrame(Frame) and putting all this stuff in that class, instead of making everything global; in this case, you can use the self keyword to bind your PhotoImage to the Frame to prevent it from being garbage-collected
Community
  • 1
  • 1
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • Thanks for your answer, will check them out now. – ThatsNotMyName Jul 21 '13 at 09:47
  • I'm currently trying to learn how to create a class now and the those if event things are buttons (Not the most efficient way I know.) – ThatsNotMyName Jul 23 '13 at 01:40
  • Sorry for the late reply been sick, but I have tried using a class and also making it global without any success, I looked up garbage collection and tried turning it off with gc.disable() without much luck either. – ThatsNotMyName Jul 29 '13 at 00:27
  • @ThatsNotMyName I've just now come to reproduce your problem (not easy when you don't have the images and do not know where to click...), but it seems to work when I make the `game` image `global`. -- see my edit. Still, I would recommend re-posting this question (or a variant thereof) on [Codereview](http://codereview.stackexchange.com/) to receive further input on how to improve your code. – tobias_k Jul 29 '13 at 13:47
  • oh hmm, that works, thanks very much for this, I can now start working on making the code more efficient, thanks for your help! – ThatsNotMyName Jul 30 '13 at 00:08
  • can't believe someone decided for such a canvas drawing scheme...this is horendous...so if you want to draw pixels, you gotta keep track of all of them ???? not really the definition of a canvas – user7082181 Mar 12 '21 at 20:44
  • @user7082181 I don't understand what you mean or how this is related to this answer. Typically, you don't draw individual pixels (there isn't even a canvas method for this), but shapes like lines, circles, polygons, etc. or images, like in this case. – tobias_k Mar 12 '21 at 22:56