Python Forum
tkinter canvas help
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
tkinter canvas help
#1
Trying to get some help with Tkinter canvas. In the code below in the def chartones() method I am trying to figure out how to access the canvas I have created in the class score above. I want to be able to edit the canvas with a w.create_text in the def chartones method but when I type w.create_text it does not recognize w it says unsolved reference. Does anybody know what I need to change to be able to edit the canvas with the chartones method?
import random
from tkinter import *
from PIL import ImageTk, Image
from tkinter import messagebox
from tkinter import simpledialog
from tkinter.messagebox import showinfo

class Score():

    def __init__(self):
        master = Tk()
        master.title('SCORECARD')

        w = Canvas(master, width=500, height=1000)
        w.pack()

        w.create_text(200, 40, text='UPPER SECTION SCORING')
        w.create_text(200, 41, text='_____________________________')
        w.create_text(55, 80, text='ONES:')
        w.create_text(55, 105, text='TWOS:')
        w.create_text(55, 130, text='THREES:')
        w.create_text(55, 155, text='FOURS:')
        w.create_text(55, 180, text='FIVES:')
        w.create_text(55, 205, text='SIXES:')
        w.create_text(55, 230, text='TOTAL SCORE:')
        w.create_text(55, 255, text='BONUS:')
        w.create_text(65, 280, text='TOTAL UPPER SECTION:')
        w.create_text(200, 355, text='LOWER SECTION SCORING')
        w.create_text(200, 356, text='____________________________')

        w.create_text(55, 415, text='THREE OF A KIND:')
        w.create_text(55, 440, text='FOUR OF A KIND:')
        w.create_text(55, 465, text='FULL HOUSE:')
        w.create_text(55, 490, text='SMALL STRAIGHT:')
        w.create_text(55, 515, text='LARGE STRAIGHT:')
        w.create_text(55, 540, text='YAHTZEE:')
        w.create_text(55, 565, text='YAHTZEE BONUS:')
        w.create_text(55, 590, text='CHANCE:')
        w.create_text(70, 615, text='LOWER SECTION TOTAL:')
        w.create_text(55, 640, text='GRAND TOTAL:')
        master.mainloop()
    
def chartones(Score):
        w.create_text(80,80,text=18)

root = Tk()
root.title('Yahtzee')
root.configure(width=1500,height=2000,bg='BLACK')
root.counter1 = 0
Reply
#2
Attach w as a member in the current instance, for example at creation time
w = self.w = Canvas(...)
Then in methods, you can write
self.w.create_text(...)
Also note that self.canvas may be a better choice than self.w .
Reply
#3
The easiest way to create a game is to use one class- In your game it would be one window to roll the dice(the main window) and another to keep score(Toplevel window). All the text in your score window so far is static- all rolled values are dynamic(changing from one game to the next). You have several options to accomplish this, one easy way is to use the Label widget with textvariable and an IntVar() function.
here's an example with your code:
import random
from tkinter import *
from PIL import ImageTk, Image
from tkinter import messagebox
from tkinter import simpledialog
from tkinter.messagebox import showinfo
 
class Yahtzee(Frame):
 
    def __init__(self, parent=None):
        self.master= parent
        self.master.title('Yahtzee!')
        Frame.__init__(self, self.master)
        self.pack(expand='yes',fill='both')
        self.canvas= Canvas(self.master, width=900,height=800,bg='black')
        self.canvas.pack(expand='yes',fill='both')
        self.ONES_Var= IntVar()
        self.make_score_card()
    def make_score_card(self):
        self.top= Toplevel()
        self.top.title('Score Card')
        self.w = Canvas(self.top, width=500, height=1000)
        self.w.pack() 
        self.w.create_text(200, 40, text='UPPER SECTION SCORING')
        self.w.create_text(200, 41, text='_____________________________')
        self.w.create_text(55, 80, text='ONES:')
        self.ONES_label= Label(self.top, textvariable=self.ONES_Var)
        self.ONES_label.place(x=80,y=70)
        self.ONES_Var.set(4)
        self.w.create_text(55, 105, text='TWOS:')
        self.w.create_text(55, 130, text='THREES:')
        self.w.create_text(55, 155, text='FOURS:')
        self.w.create_text(55, 180, text='FIVES:')
        self.w.create_text(55, 205, text='SIXES:')
        self.w.create_text(55, 230, text='TOTAL SCORE:')
        self.w.create_text(55, 255, text='BONUS:')
        self.w.create_text(65, 280, text='TOTAL UPPER SECTION:')
        self.w.create_text(200, 355, text='LOWER SECTION SCORING')
        self.w.create_text(200, 356, text='____________________________')
 
        self.w.create_text(55, 415, text='THREE OF A KIND:')
        self.w.create_text(55, 440, text='FOUR OF A KIND:')
        self.w.create_text(55, 465, text='FULL HOUSE:')
        self.w.create_text(55, 490, text='SMALL STRAIGHT:')
        self.w.create_text(55, 515, text='LARGE STRAIGHT:')
        self.w.create_text(55, 540, text='YAHTZEE:')
        self.w.create_text(55, 565, text='YAHTZEE BONUS:')
        self.w.create_text(55, 590, text='CHANCE:')
        self.w.create_text(70, 615, text='LOWER SECTION TOTAL:')
        self.w.create_text(55, 640, text='GRAND TOTAL:')        
     
    
if __name__ =='__main__': 
    root = Tk()
    Yahtzee(root)    
    root.mainloop()
Reply
#4
What I'm trying to do here is create a Yahtzee game and use buttons to chart the score on the canvas after each button is clicked. When I try and click on ones to use the chart ones method I'm getting an error with this statement: button1.bind('<Button-1>', Score.chartones()). It's saying TypeError: chartones() missing 1 required positional argument: 'self'. If I add self in there it's saying name Self is not defined.
import random
from tkinter import *
from PIL import ImageTk, Image
from tkinter import messagebox
from tkinter import simpledialog
from tkinter.messagebox import showinfo

class Score():

    def __init__(self):
        master = Tk()
        master.title('SCORECARD')

        w = self.w= Canvas(master, width=500, height=1000)
        w.pack()

        w.create_text(200, 40, text='UPPER SECTION SCORING')
        w.create_text(200, 41, text='_____________________________')
        w.create_text(55, 80, text='ONES:')
        w.create_text(55, 105, text='TWOS:')
        w.create_text(55, 130, text='THREES:')
        w.create_text(55, 155, text='FOURS:')
        w.create_text(55, 180, text='FIVES:')
        w.create_text(55, 205, text='SIXES:')
        w.create_text(55, 230, text='TOTAL SCORE:')
        w.create_text(55, 255, text='BONUS:')
        w.create_text(65, 280, text='TOTAL UPPER SECTION:')
        w.create_text(200, 355, text='LOWER SECTION SCORING')
        w.create_text(200, 356, text='____________________________')

        w.create_text(55, 415, text='THREE OF A KIND:')
        w.create_text(55, 440, text='FOUR OF A KIND:')
        w.create_text(55, 465, text='FULL HOUSE:')
        w.create_text(55, 490, text='SMALL STRAIGHT:')
        w.create_text(55, 515, text='LARGE STRAIGHT:')
        w.create_text(55, 540, text='YAHTZEE:')
        w.create_text(55, 565, text='YAHTZEE BONUS:')
        w.create_text(55, 590, text='CHANCE:')
        w.create_text(70, 615, text='LOWER SECTION TOTAL:')
        w.create_text(55, 640, text='GRAND TOTAL:')

        master.mainloop()

    def chartones(self):
            self.w.create_text(110, 80, text='score')


root = Tk()
root.title('Yahtzee')
root.configure(width=1500,height=2000,bg='BLACK')
root.counter1 = 0

def on_click(event):
    event.widget.config(bg='red')
    root.counter1 += 1

def chartscore():

    root = Toplevel()
    root.title('Chart Score')
    label = Label(root, text="Please click the category you want to chart your score in:").pack()
    button1 = Button(root, text="ONES", bg="white", fg="black", width=20, font=("Times", 12))
    button2 = Button(root, text="TWOS", bg="white", fg="black", width=20, font=("Times", 12))
    button3 = Button(root, text="THREES", bg="white", fg="black", width=20, font=("Times", 12))
    button4 = Button(root, text="FOURS", bg="white", fg="black", width=20, font=("Times", 12))
    button5 = Button(root, text="FIVES", bg="white", fg="black", width=20, font=("Times", 12))
    button6 = Button(root, text="SIXES", bg="white", fg="black", width=20, font=("Times", 12))
    button7 = Button(root, text="THREE OF A KIND", bg="white", fg="black", width=20, font=("Times", 12))
    button8 = Button(root, text="FOUR OF A KIND", bg="white", fg="black", width=20, font=("Times", 12))
    button9 = Button(root, text="FULL HOUSE", bg="white", fg="black", width=20, font=("Times", 12))
    button10 = Button(root, text="SMALL STRAIGHT", bg="white", fg="black", width=20, font=("Times", 12))
    button11 = Button(root, text="LARGE STRAIGHT", bg="white", fg="black", width=20, font=("Times", 12))
    button12 = Button(root, text="YAHTZEE", bg="white", fg="black", width=20, font=("Times", 12))
    button13 = Button(root, text="YAHTZEE BONUS", bg="white", fg="black", width=20, font=("Times", 12))
    button14 = Button(root, text="CHANCE", bg="white", fg="black", width=20, font=("Times", 12))

    button1.pack()
    button1.bind('<Button-1>', Score.chartones())
    button2.pack()
    button2.bind('<Button-1>', on_click)
    button3.pack()
    button3.bind('<Button-1>', on_click)
    button4.pack()
    button4.bind('<Button-1>', on_click)
    button5.pack()
    button5.bind('<Button-1>', on_click)
    button6.pack()
    button6.bind('<Button-1>', on_click)
    button7.pack()
    button7.bind('<Button-1>', on_click)
    button8.pack()
    button8.bind('<Button-1>', on_click)
    button9.pack()
    button9.bind('<Button-1>', on_click)
    button10.pack()
    button10.bind('<Button-1>', on_click)
    button11.pack()
    button11.bind('<Button-1>', on_click)
    button12.pack()
    button12.bind('<Button-1>', on_click)
    button13.pack()
    button13.bind('<Button-1>', on_click)
    button14.pack()
    button14.bind('<Button-1>', on_click)
    mainloop()

def thirdroll():
    global my_img
    global image2
    global image3
    global image4
    global image5
    global image6
    top = Toplevel()
    top.title('Third Roll')
    label2 = Label(top, text="Click Chart Score at the bottom of the screen then choose a category to score:").pack()
    label = Label(top,text="Your third roll is:").pack()
    remdice = 5 - root.counter1
    my_img = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_1.png"))
    image2 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_2.png"))
    image3 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_3.png"))
    image4 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_4.png"))
    image5 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_5.png"))
    image6 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_6.png"))
    butn2 = Button(top, text='View Scorecard', width=15, command=Score).place(x=20, y=100)
    butn3 = Button(top, text='Chart Score', width=15, command=chartscore).place(x=20, y=50)

    dice = [my_img, image2, image3, image4, image5, image6]

    rdice = random.choice(dice)
    rdice2 = random.choice(dice)
    rdice3 = random.choice(dice)
    rdice4 = random.choice(dice)
    rdice5 = random.choice(dice)

    if remdice == 1:
          btn1 = Button(top, image=rdice)
          btn1.pack()

    if remdice == 2:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn2 = Button(top, image=rdice2)
          btn2.pack()

    if remdice == 3:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn3 = Button(top, image=rdice3)
          btn3.pack()

    if remdice == 4:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn3 = Button(top, image=rdice3)
          btn3.pack()
          btn4 = Button(top, image=rdice4)
          btn4.pack()

    if remdice == 5:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn3 = Button(top, image=rdice3)
          btn3.pack()
          btn4 = Button(top, image=rdice4)
          btn4.pack()
          btn5 = Button(top, image=rdice5)
          btn5.pack()

def secondroll():
    global my_img
    global image2
    global image3
    global image4
    global image5
    global image6
    top = Toplevel()
    top.title('Second Roll')
    lbl2 = Label(top,text="Click on the dice you would like to keep for this round. Then click third roll at the bottom of the screen.").pack()
    label = Label(top, text="Your second roll is:").pack()
    remdice = 5 - root.counter1
    my_img = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_1.png"))
    image2 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_2.png"))
    image3 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_3.png"))
    image4 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_4.png"))
    image5 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_5.png"))
    image6 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_6.png"))
    butn = Button(top, text="Third Roll", width=10, command=thirdroll).place(x=400, y=100)
    butn2 = Button(top, text='View Scorecard', width=15, command=Score).place(x=100, y=100)
    butn3 = Button(top, text='Chart Score', width=15, command=chartscore).place(x=100, y=50)

    dice = [my_img, image2, image3, image4, image5, image6]

    rdice = random.choice(dice)
    rdice2 = random.choice(dice)
    rdice3 = random.choice(dice)
    rdice4 = random.choice(dice)
    rdice5 = random.choice(dice)

    if remdice == 1:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn1.bind('<Button-1>', on_click)

    if remdice == 2:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn1.bind('<Button-1>', on_click)
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn2.bind('<Button-1>', on_click)

    if remdice == 3:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn1.bind('<Button-1>', on_click)
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn2.bind('<Button-1>', on_click)
          btn3 = Button(top, image=rdice3)
          btn3.pack()
          btn3.bind('<Button-1>', on_click)

    if remdice == 4:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn1.bind('<Button-1>', on_click)
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn2.bind('<Button-1>', on_click)
          btn3 = Button(top, image=rdice3)
          btn3.pack()
          btn3.bind('<Button-1>', on_click)
          btn4 = Button(top, image=rdice4)
          btn4.pack()
          btn4.bind('<Button-1>', on_click)

    if remdice == 5:
          btn1 = Button(top, image=rdice)
          btn1.pack()
          btn1.bind('<Button-1>', on_click)
          btn2 = Button(top, image=rdice2)
          btn2.pack()
          btn2.bind('<Button-1>', on_click)
          btn3 = Button(top, image=rdice3)
          btn3.pack()
          btn3.bind('<Button-1>', on_click)
          btn4 = Button(top, image=rdice4)
          btn4.pack()
          btn4.bind('<Button-1>', on_click)
          btn5 = Button(top, image=rdice5)
          btn5.pack()
          btn5.bind('<Button-1>', on_click)

def yahtzee():
      global my_img
      global image2
      global image3
      global image4
      global image5
      global image6
      top = Toplevel()
      top.title('First Roll')
      lbl2 = Label(top, text="Click on the dice you would like to keep for this round. Then click second roll at the bottom of the screen").pack()
      lbl = Label(top, text="Your first roll is:").pack()
      my_img = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_1.png"))
      image2 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_2.png"))
      image3 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_3.png"))
      image4 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_4.png"))
      image5 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_5.png"))
      image6 = ImageTk.PhotoImage(Image.open("C:\\Users\\Dan\\Desktop\\Alea_6.png"))
      butn = Button(top, text="Second Roll", width=10, command=secondroll).place(x=400, y=500)
      butn2 = Button(top, text='View Scorecard', width=15,command=Score).place(x=400,y=600)
      butn3 = Button(top, text='Chart Score',width=15,command=chartscore).place(x=50,y=500)

      dice = [my_img, image2, image3, image4, image5, image6]

      rdice = random.choice(dice)
      rdice2 = random.choice(dice)
      rdice3 = random.choice(dice)
      rdice4 = random.choice(dice)
      rdice5 = random.choice(dice)

      btn1 = Button(top, image=rdice)
      btn1.pack()
      btn1.bind('<Button-1>', on_click)
      btn2 = Button(top, image=rdice2)
      btn2.pack()
      btn2.bind('<Button-1>', on_click)
      btn3 = Button(top, image=rdice3)
      btn3.pack()
      btn3.bind('<Button-1>', on_click)
      btn4 = Button(top, image=rdice4)
      btn4.pack()
      btn4.bind('<Button-1>', on_click)
      btn5 = Button(top, image=rdice5)
      btn5.pack()
      btn5.bind('<Button-1>', on_click)

def quit():
    exit()

def rules():
    showinfo('RULES','The game begins by the player rolling a cup of five dice. The player may roll the 5 dice a total'
          ' of 3 times. After each roll the player may set aside any dice they wish to keep for scoring and place the others'
          ' back in the cup. Then the player must choose a category to score the points. Scoring can be charted at any'
          ' point in the round. The player does not have to roll the dice three times.'
    '\n\nSCORING\n'

    '\nTo chart your score choose one of the categories on the scorecard. Once you place a score in a category \n'
          'it cannot be scored again the rest of the game, except for the Yahtzee Bonus. The player with the most \n'
          'points after all categories have been filled wins the game. Listed below is an explanation of the scoring for each category:\n\n'
          'UPPER SECTION SCORING\n\n'
          'ONES: The sum of all the 1s rolled by the player.\n'
          'TWOS: The sum of all the 2s rolled by the player.\n'
          'THREES: The sum of all the 3s rolled by the player.\n'
          'FOURS: The sum of all the 4s rolled by the player.\n'
          'FIVES: The sum of all the 5s rolled by the player.\n'
          'SIXES: The sum of the 6s rolled by the player.\n'
          'TOTAL SCORE: The sum of the 6 categories above.\n'
          'BONUS: If the total score is 63 or greater a bonus score of 35 is added.\n'
          'TOTAL UPPER SECTION: The total score plus the bonus if one is given.\n\n'

          'LOWER SECTION SCORING\n\n'

          'THREE OF A KIND: Scores the total of all dice and must include 3 of the same number.\n'
          'FOUR OF A KIND: Scores the total of all dice and must include 4 of the same number.\n'
          'FULL HOUSE: Scored as 25 points and must include 3 dice of one number and 2 dice of another number.\n'
          'SMALL STRAIGHT: Scored as 30 points and is a sequence of 4 numbers.\n'
          'LARGE STRAIGHT: Scored as 40 points and is a sequence of 5 numbers.\n'
          'YAHTZEE: Scored as 50 points and is a 5 of a kind.(5 dice of the same number)\n'
          'CHANCE: Total of all 5 dice.\n'
          'YAHTZEE BONUS: Scored as 100 points and this category is charted for each additonal Yahtzee rolled.\n'
          'LOWER SECTION TOTAL: Sum of all categories in the lower section.\n'

          '\nGRAND TOTAL: The sum of the upper section total and the lower section total.\n')



button1= Button(root, text="Quit", bg="white", fg="black", width=20, font=("Times", 12),command=quit)
button2= Button(root, text="Rules", bg="white", fg="black", width=20, font=("Times", 12),command=rules)
button3= Button(root, text="Play A Game Of Yahtzee", bg="white", fg="black", width=20, font=("Times", 12),command=yahtzee)

button1.grid(row=1,column=4, padx=40, pady=10)
button2.grid(row=1,column=5, padx=40, pady=10)
button3.grid(row=1,column=6,padx=40,pady=10)

mainloop()
Reply
#5
If you want to bind button1 to chartones(), you need a Score instance and use
button1.bind('<Button-1>', score.chartones()) # score is an instance of Score, not the class itself
The use of master = Tk() is Score.__init__() looks weird. You already have a Tk instance (root). It should perhaps be master = TopLevel().
Reply
#6
Please paste the complete trace with appropriate tag
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  tkinter.TclError: can't invoke "canvas" command cybertooth 8 5,924 Feb-23-2023, 06:58 PM
Last Post: deanhystad
  [Tkinter] Clickable Rectangles Tkinter Canvas MrTim 4 8,799 May-11-2021, 10:01 PM
Last Post: MrTim
  [Tkinter] Draw a grid of Tkinter Canvas Rectangles MrTim 5 7,865 May-09-2021, 01:48 PM
Last Post: joe_momma
Thumbs Up tkinter canvas; different page sizes on different platforms? philipbergwerf 4 4,089 Mar-27-2021, 05:04 AM
Last Post: deanhystad
  how to resize image in canvas tkinter samuelmv30 2 17,698 Feb-06-2021, 03:35 PM
Last Post: joe_momma
  how to rotate lines in tkinter canvas helpmewithpython 1 3,408 Oct-06-2020, 06:56 PM
Last Post: deanhystad
  Tkinter function to clear old canvas and start a fresh "operation" zazas321 5 9,390 Oct-01-2020, 04:16 AM
Last Post: zazas321
  question on tkinter canvas PhotoImage gr3yali3n 1 2,122 Sep-05-2020, 12:18 PM
Last Post: Larz60+
  TKinter coordinate system (canvas) Bhoot 1 2,930 Mar-23-2020, 04:30 PM
Last Post: Larz60+
  [Tkinter] Scrollbar doesn't work on Canvas in Tkinter DeanAseraf1 3 9,343 Sep-19-2019, 03:26 PM
Last Post: joe_momma

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020