Write a Python program that draws a circle with radius 50 pixels and centered at the center of the canvas. Give the canvas white background color and make it expand with its frame whenever the user resizes the frame. The program will respond to some mouse and keyboard events as described below.

Whenever the left mouse button is pressed, display a message indicating whether the mouse pointer is inside the circle as shown in the figures below. The center of the message's baseline should be at the center of the circle. Moreover, the message should be displayed using a random color. You can use the following method to generate random colors:

Your program also uses the arrow keys to move the circle left, right, up, or down when the Left arrow key, Right arrow key, Up arrow key, or Down arrow key is clicked. Every arrow-key click should move the circle 5 pixels in the appropriate direction. Delete any displayed text when the circle is moved. To bind the Up arrow-key with the event handler self.moveCircle(), you can use the code:

using the arrow keys to move the circle, then clicking the left mouse button will always display the message at the center of circle.

This is what i have so far.

from Tkinter import * 

class Circle(Frame):
    def __init__(self):
        Frame.__init__(self, bg = "white")
        self.master.title("circle")
        self.grid()

        self.radius = 50 

        self.canvas = Canvas(self, width = 400, height = 400, bg = "white")
        self.canvas.grid(row = 0, column = 0)
        self.canvas.create_oval(200 - self.radius, 200 - self.radius,
                                200 + self.radius, 200 + self.radius, tags = "circle")
        self.canvas.create_text(200, 200, text = "", tags = "text")


        self.master.bind('<Configure>', self.resize)
        self.canvas.bind('<Button-1>', self.getWords)
        self.canvas.bind('<Up>', self.moveCircle)
        self.canvas.bind('<Down>', self.moveCircle)
        self.canvas.bind('<Left>', self.moveCircle)
        self.canvas.bind('<Right>', self.moveCircle)
        self.canvas.focus_set()

    def resize(self, event):
        self.canvas.configure(width = event.width-4, height = event.height-4)

    def getWords(self, event):
        color = self.getRandomColor()
        print event.x, event.y
        x = 200
        y = 200
        if (150, 150) < (event.x, event.y) < (250, 250):
            self.canvas.delete("text")
            self.canvas.create_text(x, y, text = "Mouse pointer is inside the circle",
                                    fill = color, tags = "text")
        else:
            self.canvas.delete("text")
            self.canvas.create_text(x, y, text = "Mouse pointer is outside the circle",
                                    fill = color, tags = "text")


    def getRandomColor(self):
        """ Generates and returns a random color string such as '#c2f74a'"""
        digits = "0123456789abcdef"
        color = "#"
        from random import randint
        for i in range(6):
            randomIndex = randint(0, 15)
            color += digits[randomIndex]

        return color

    def moveCircle(self, event):
        """move circle up, down, left or right when user clicks an arrow key"""
        if event.keysym == "Up":
            self.canvas.move("circle", 0, -5)
            self.canvas.move("text",0, -5)
            self.canvas.update()
        elif event.keysym == "Down":
            self.canvas.move("circle", 0, 5)
            self.canvas.move("text",0, 5)
            self.canvas.update()
        elif event.keysym == "Left":
            self.canvas.move("circle", -5, 0)
            self.canvas.move("text", -5, 0)
            self.canvas.update()
        else:
            self.canvas.move("circle", 5, 0)
            self.canvas.move("text", 5, 0)
            self.canvas.update()



def main():
    Circle().mainloop()

main()

I cant get the text to say if its in the circle or not. and i cant get the text to reprint in the center of the circle when the circle is moved.

This statement is part of your problem

        self.master.bind('<Configure>', self.resize)

Also, you misspelled "tag". Other than that, moving the circle works fine for me. Since you always print the text in the same place and test the same coordinates, you will always get the same results. You have to keep track of the center of the circle and see if the mouse click location is within the radius, i.e use a right triangle to get the distance from the mouse click to the center and test for less than the radius.

I would make moveCircle less redundant with the following code. Finally, I would suggest that you select different names for the tags as "circle" and "text" can be confusing since Tkinter already uses those names.

    def moveCircle(self, event):
        """move circle up, down, left or right when user clicks an arrow key"""
        x=0
        y=0
        if event.keysym == "Up":
            y = -5
        elif event.keysym == "Down":
            y = 5
        elif event.keysym == "Left":
            x = -5
        else:
            x = 5

        self.canvas.move("circle", x, y)
        self.canvas.move("text", x, y)
        self.canvas.update()

Edited 4 Years Ago by woooee

In order to get the desired effect for the method getWord(), you will need to make three changes. First, you'll need to track the centerpoint of the circle; a simple list pair would do nicely:

self.center = [200, 200]  # initialize to the original center of the canvas

Then you need to alter moveCircle() so that the changes in the centerpoint are tracked as the circle moves:

    def moveCircle(self, event):
        """move circle up, down, left or right when user clicks an arrow key"""
        x=0
        y=0
        if event.keysym == "Up":
            y = -5
        elif event.keysym == "Down":
            y = 5
        elif event.keysym == "Left":
            x = -5
        else:
            x = 5

        self.canvas.move("circle", x, y)
        self.canvas.move("text", x, y)
        self.center[0] += x
        self.center[1] += y
        self.canvas.update()

Finally, you'll need to change the conditional of in getWords() to calculate the distance between the the current centerpoint and the mouse-down location, and compare it to the radius of the circle:

    def getWords(self, event):
        color = self.getRandomColor()
        self.canvas.delete("text")

        distance = math.sqrt((self.center[0] - event.x) ** 2 + (self.center[1] - event.y) ** 2)
        place = ''

        if distance <= self.radius:
            place = 'inside'
        else:
            place = 'outside'

        self.canvas.create_text(self.center[0],  self.center[1],
                                    text = "Mouse pointer is %s the circle" % place,
                                    fill = color, tag = "text")

This should do the job nicely. Note that I used another instance variable, self.radius, rather than hard-coding the 50 in; this would allow you to change the size of the circle dynamically, later on, and still let the function work.

BTW, what is the resize() method meant for? It isn't used in the program anywhere, but it appears to resize the canvas. Is that what you wanted, or were you looking at resizing the circle?

Edited 4 Years Ago by Schol-R-LEA

This article has been dead for over six months. Start a new discussion instead.