Kein Attribut 'create_oval' im Objekt '_tkinter.tkapp'

Fragen zu Tkinter.
Antworten
Atalanttore
User
Beiträge: 129
Registriert: Freitag 6. August 2010, 17:03

Samstag 23. Juni 2018, 21:15

Hallo

Ich beschäftige mich gerade mit Tkinter in Python 3.

Aktuell würde ich gerne weiße Punkte auf einen schwarzen Bildschirm im Vollbildmodus zeichnen und deren Position mithilfe einer Schleife dauernd abändern.

Mein Code sieht wie folgt aus:

Code: Alles auswählen

from tkinter import *

def paint(x, y):
    x1, y1 = (x - 5), (y - 5)
    x2, y2 = (x + 5), (y + 5)
    root.create_oval(x1, y1, x2, y2, fill="#ffffff")


if __name__ == "__main__":
    root = Tk()
    root.attributes('-fullscreen', True)
    root.geometry("%dx%d+0+0" % (root.winfo_screenwidth(), root.winfo_screenheight()))
    root.focus_set()
    root.configure(background='black')
    root.bind("<Escape>", lambda e: root.quit())

    paint(500,500) #Test

    root.mainloop()

Leider kommt es beim Aufruf der Funktion paint() zu folgendem Fehler:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/ata/source/Test/main.py", line 19, in <module>
    paint(500,500) #Test
  File "/home/ata/source/Test/main.py", line 8, in paint
    root.create_oval(x1, y1, x2, y2, fill="#ffffff")
  File "/usr/lib/python3.6/tkinter/__init__.py", line 2098, in __getattr__
    return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'create_oval'
Was mache ich falsch?

Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 1453
Registriert: Samstag 2. Juni 2018, 10:21

Samstag 23. Juni 2018, 21:43

Du rufst eine Methode von `Canvas`-Objekten auf einem `Tk`-Objekt auf.

Ansonsten `root` sollte nicht auf Modulebene bestehen sondern in einer Funktion. Also der ganze Code in dem ``if``-Zweig. Was dann auch dazu führt, das man der `paint()`-Funktion nicht nur die Koordinaten übergeben muss, sondern auch das Objekt auf dem `create_oval()` aufgerufen wird.

Code: Alles auswählen

    **** COMMODORE 64 BASIC V2 ****
 64K RAM SYSTEM  38911 BASIC BYTES FREE
   CYBERPUNX RETRO REPLAY 64KB - 3.8P
READY.
█
Atalanttore
User
Beiträge: 129
Registriert: Freitag 6. August 2010, 17:03

Sonntag 24. Juni 2018, 15:46

Okay, dann kann es ja nicht funktionieren.

Ich habe den Code mal angepasst, damit das Programm läuft, und zum Test eine Schleife zum Anordnen der Punkte in einem Kreis eingebaut.

Code: Alles auswählen

from tkinter import *
from math import cos, sin


def point_on_circle(radius, angle, center_x, center_y):
    x = center_x + (radius * cos(angle))
    y = center_y + (radius * sin(angle))
    return x, y


def paint(x, y, window):
    x1, y1 = (x - 8), (y - 8)
    x2, y2 = (x + 8), (y + 8)
    window.create_oval(x1, y1, x2, y2, fill="#ffffff")


def main():
    root = Tk()
    root.attributes("-fullscreen", True)
    root.focus_set()
    root.bind("<Escape>", lambda e: root.quit())

    width = root.winfo_screenwidth()
    height = root.winfo_screenheight()
    center_x = width / 2
    center_y = height / 2

    window = Canvas(root, width=width, height=height, bg="black")
    window.pack()

    for i in range(0, 360, 15):
        x, y = point_on_circle(300, i, center_x, center_y)
        print(x, y)
        paint(x, y, window)

    root.mainloop()


if __name__ == "__main__":
    main()
Komischerweise fehlen ein paar Punkte auf dem Kreis und die Abstände zwischen den Punkten sind auch nicht so akkurat wie erwartet.
Bild

Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 1453
Registriert: Samstag 2. Juni 2018, 10:21

Sonntag 24. Juni 2018, 15:52

@Atalanttore: Das ist nur komisch solange man davon ausgeht das `cos()` und `sin()` Grad als Einheit erwarten, was sie nicht tun. Das `math`-Modul bietet aber eine Funktion zum Umrechnen. :-)

Code: Alles auswählen

    **** COMMODORE 64 BASIC V2 ****
 64K RAM SYSTEM  38911 BASIC BYTES FREE
   CYBERPUNX RETRO REPLAY 64KB - 3.8P
READY.
█
Atalanttore
User
Beiträge: 129
Registriert: Freitag 6. August 2010, 17:03

Sonntag 24. Juni 2018, 16:27

Wie folgt angepasst funktioniert es.

Code: Alles auswählen

    x = center_x + (radius * math.cos(math.radians(angle)))
    y = center_y + (radius * math.sin(math.radians(angle)))
Wie konnte ich nur davon ausgehen, dass `cos()` und `sin()` Grad und nicht Radiant als Einheit erwarten ... :oops:

Gruß
Atalanttore
Antworten