How can I fix < TypeError: paint() missing 2 required positional arguments: 'event' and 'window' >

Question:

I’m trying to create a window, which can draw some circles. Using the code below:

from tkinter import *
from tkinter import Tk
from tkinter import Canvas as c

window = Tk()
window.configure(background = "grey")
window.title("Canvas - Draw Shapes")

f_top = Frame(window)
f_bot = Frame(window)
f_top.pack()
f_bot.pack()

# elements
button_1 = Button(f_bot, text='Левая кнопка')
button_2 = Button(f_bot, text='Правая кнопка')
button_1.pack(side=LEFT)
button_2.pack(side=LEFT)

# setting up the canvas
canvas = Canvas(f_top, width=500, height=300, bg = "white")
canvas.pack(expand = YES, fill = BOTH)

def paint(event, window):
    x1, y1 = ( event.x - 4 ), ( event.y - 4 )
    x2, y2 = ( event.x + 4 ), ( event.y + 4 )
    window.create_oval( x1, y1, x2, y2, fill = black )

canvas.bind('<B1-Motion>', paint())
window.mainloop()

This code returns

TypeError: paint() missing 2 required positional arguments: ‘event’ and ‘window’

I’ve tried to use self and ‘event’ and some others as the first argument and ‘window’, ‘canvas’ as the second.

Asked By: Rumata_VII

||

Answers:

The issue is that your event binding is set up incorrectly.
It should be: ('<B1-Motion>', paint) (note the lack of () after the function name). This should pass the event to paint automatically.

Also, you should be able to remove the window argument. What you want here is canvas.create_oval. You don’t need a special argument for this since canvas is in the global scope.

And one last thing – you’ll need quotes around the color string for fill.

def paint(event):
    x1, y1 = (event.x - 4), (event.y - 4)
    x2, y2 = (event.x + 4), (event.y + 4)
    canvas.create_oval(x1, y1, x2, y2, fill='black')

Essentially what was happening is that when you wrote canvas.bind('<B1-Motion>', paint()), you were calling paint() with 0 arguments, and (as originally written), it expected 2 arguments. By removing the parenthesis, you’re no longer calling the function needlessly. Instead, you’re assigning it as the callback for the event binding.

Answered By: JRiggles

This is the problem:

canvas.bind('<B1-Motion>', paint())

Because paint() has the parentheses, it is being called right now, which isn’t what you want.

The purpose of canvas.bind() is to specify a function which will be called later, in response to some event.

So, the fix is probably to just pass the function name:

canvas.bind('<B1-Motion>', paint)

And then internally, the canvas.bind() function saves a reference to that function, so it can be called later.

Answered By: John Gordon
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.