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.
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
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
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.
This is the problem:
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:
And then internally, the
canvas.bind() function saves a reference to that function, so it can be called later.