0

I'm making a card game (called monster master) to develop my python skills, specifically OOP.

I have a GUI that has a few static objects: Player 1's side of the table, Player 2's side, a wee line in the middle and I'm now trying to implement an 'end turn' button.

I have tried a lot of different things to try to get this button to display, but I just can't get it to appear even if there are no errors. Just saying that there are a few commented out lines that I've temporarily taken away for the sake of trying to understand the problem with this button.

Here's the code that I'm currently using to try:

def RunGame():
class App():
    """docstring for App"""

    def draw():
        # Setting up canvas dimensions

        canvas_width = 640
        canvas_height = 480

        master = Toplevel()
        master.title("Monster Master by Charles Cameron - Game")
        master.resizable(width=False, height=False)
        master.geometry("640x480")

        w = Canvas(master, 
                   width=canvas_width, 
                   height=canvas_height)
        w.pack()

        # Drawing static objects 
        CentrePoints = [(0, canvas_height/2), (canvas_width/2, canvas_height/2), 
            (canvas_width, canvas_height/2)] 
            #Left, centre and right centres (save me from retyping them)

        Player1Area = w.create_rectangle(CentrePoints[0], canvas_width,
            canvas_height, fill="#303AFE") #Player1 Area
        Player2Area = w.create_rectangle(0, 0, CentrePoints[2], 
            fill="#C31B1B") #Player2 Area

        Barrier = w.create_line(CentrePoints[0], CentrePoints[2], 
            fill="#0090E3", width=20) # Centre barrier

        # class GameBtn():
        #   class EndTurnBtn():
        #       def __init__(self, BtnName, master):
        BtnName = Button(master, bg="white", command=lambda:print("Clicked!"))

        image = ImageTk.PhotoImage(file="imgs\EndTurn.png")
        BtnName.config(image=image, width="70", height="70")

        BtnName.pack(side=RIGHT)

        # ChangeTurn = GameBtn.EndTurnBtn('ChangeTurn', master)

        master.mainloop()

Window = App()
App.draw()

The button code for the actual button worked fine when I tried it in its own script but stopped working when I put it inside this program.

Hope it's not too dumb a question to ask, quite an amateur at python still and honestly can't find the answer anywhere online.

Many thanks

2
  • You also have to ensure that your PhotoImage object stays intact, as tkinter DOES NOT keep a reference to the object - once your image varaible goes out of scope the button will go blank. See the note at the bottom of the page - effbot.org/tkinterbook/photoimage.htm Commented Sep 13, 2017 at 8:53
  • you don't/shouldn't use TopLevel unless you actually intend to use both the root window and the new window. I think your code has other issues too (for instance what is ImageTK) Commented Sep 13, 2017 at 9:08

1 Answer 1

2

Your button exists, but it's past the edge of the window. This is because you made your window 640x480, and then completely filled it with a 640x480 canvas. Remove the master.geometry("640x480") line and the window will stretch to contain both your canvas and your button.

You might be thinking "but I don't want the button to appear to the side of the canvas. I want the button to be on the canvas. The canvas only really exists because I wanted to color sections of the background". Embedding widgets on a canvas is possible using create_window (see How to place a widget in a Canvas widget in Tkinter?), but it may be more practical to create colored backgrounds by stacking Frame objects together and giving them individual colors. Example:

from tkinter import Tk, Frame, Button

root = Tk()
root.geometry("640x480")
top_player_frame = Frame(root, height=230, bg="red")
barrier = Frame(root, height=20, bg="green")
bottom_player_frame = Frame(root, height = 230, bg="blue")

#configure column 0 so frames can stretch to fit width of window
root.columnconfigure(0, weight=1)

top_player_frame.grid(row=0, sticky="we")
barrier.grid(row=1, sticky="we")
bottom_player_frame.grid(row=2, sticky="we")

bottom_player_end_turn_button = Button(bottom_player_frame, text="End Turn")
#use `place` here because `pack` or `grid` will collapse the frame to be only as tall as all the widgets it contains, i.e. just this button
bottom_player_end_turn_button.place(x=10,y=10)

root.mainloop()

Result:

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the reply, that seems to work great apart from it doesn't solve the issue I've been having with making the button an image. I've been trying to use TkImage and/or photoimage but I've been having the issue of 'image pyimage1 doesn't exist' no matter what I pass in for the image parameter.
@MrMeowMeow, That might be caused by the PhotoImage premature garbage collection bug. If the fix described on that page doesn't help, consider making a new post describing your image button problem.

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.