Programm läuft immer langsamer

Fragen zu Tkinter.
Antworten
bas_oldy
User
Beiträge: 16
Registriert: Donnerstag 23. August 2018, 20:09

Hallo Python3-Gemeinde,

als Neuling, der bisher nur mit verschiedenen BASIC-Dialekten gearbeitet hat, mache ich noch viele Fehler und habe viele Fragen. Kann mir jemand schreiben, warum mein Program "RGB_t.py", das Kreise zeigt, deren Füllfarbe sich schrittweise ändert, mit jedem Schritt langsamer wird. Die gespeicherten Zeiten zeigen einen Anstieg von etwa 0,02 sec auf etwa 0,5 sec pro Schritt. Ist das eine Eigenschaft von Python oder mache ich das ganz falsch? Vielen Dank für eure Hilfe.

bas_oldy

# RGB_t.py
from tkinter import *
import time
fen0 = Tk()
fen0.title("RGB_t.py")
fen1 = Canvas(fen0, width=700, height=700, bg="white")
fen1.pack()
daten = open('zeit.txt', 'a')
t0 = timt.time()
for i in range(256):
tt = str(time.time() - t0)
daten.write(tt +" \n")
fa = hex(i)
if i<16
fb = '0'+str(fa[2:])
else:
fb = str(fa[2:])
fc = "#"+fb+fb+fb
fen1.create_oval(250, 250, 450, 450, fill=fc)
fc = "#"+fb+"0000"
fen1.create_oval(250, 25, 450, 225, fill=fc)
fc = "#"+"ff"+fb+fb
fen1.create_oval(250, 475, 450, 675, fill=fc)
fc = "#"+"00"+fb+"00"
fen1.create_oval(25, 135, 225, 335, fill=fc)
fc = "#"+fb+"ff"+fb
fen1.create_oval(25, 365, 225, 565, fill=fc)
fc = "#"+"00"+"00"+fb
fen1.create_oval(475, 135, 675, 335, fill=fc)
fc = "#"+fb+fb+"ff"
fen1.create_oval(475, 365, 675, 565, fill=fc)
fen0.update()
daten.close()
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Sternchenimporte sind schlecht, Die Variablennamen sind mehr als schlecht. warum nennst Du alles fen oder fa/fb/fc? Um maximale Verwirrung und Tippfehlersensitivität zu erreichen?

Das Programm ist auch nicht lauffähig, weil es einen Syntaxfehler gibt.

Wenn man eine zweistellige Hex-Zahl will, benutzt man format:

Code: Alles auswählen

fb = "{:02x}".format(i)
`str` auf einen String anzuwenden ist auch sinnfrei.

Statt immer mehr Kreise zu erzeugen, solltest Du nur die Farbe der schon erstellten Kreise ändern. Dann wird es auch nicht langsamer.
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bas_oldy: `Canvas` ist Vektorgrafik, das heisst alles was Du da erzeugst sind Objekte die immer wieder gezeichnet werden und je mehr das werden, um so länger dauert das. Da Du die Ovale immer übereinander zeichnest, macht das keinen Sinn dafür immer neue zu nehmen. Stattdessen würde man die *einmal* zeichnen, und dann nur noch die Farbe ändern.

Anstelle der `hex()`-Funktion, da dann zwei Zeichen entfernen, und gegebenfalls wieder eine führende Null dran zu pappen, solltest Du Dir mal Zeichenkettenformatierung mit der `format()`-Methode anschauen. Da kann man auch Hexadezimal formatieren mit entsprechend vielen Stellen.

`fen0`, `fen1`, `fc`, `fb` — sind alles keine guten Namen. Ein Name sollte dem Leser vermitteln was der Wert bedeutet, ohne das er raten muss. Also keine komischen Abkürzungen und keine angehängten Nummern. `fenster`, `canvas`, `value`, und `color` wären besser.

Ich bin ja fast sicher das man den Code in der Schleife ebenfalls in einer Schleife mit einem Durchgang pro Oval ausdrücken kann.

Die `update()`-Methode in einer Schleife ist nicht der normale Weg für GUI-Programmierung. Tk hat wie die meisten GUI-Rahmenwerke eine Hauptschleife und man kann mit der `after()`-Methode für regelmässige Rückrufe sorgen in denen dann etwas gemacht werden kann.

Bei jedem nicht-trivialen GUI-Programm kommt man um objektorientierte Programmierung (OOP) nicht herum.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bas_oldy: Wenn man Probleme mit Code hat, wäre es sinvoll auch *den* Code zu zeigen, denn neben den beiden Syntaxfehlern ist da auch noch mindestens ein `NameError` enthalten.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion mit dem Namen `main()`.

Code: Alles auswählen

from collections import namedtuple
import time
import tkinter as tk


Circle = namedtuple('Circle', 'id color_template')


def color_animation(canvas, circles, values):
    try:
        value = next(values)
    except StopIteration:
        pass
    else:
        for circle in circles:
            canvas.itemconfig(
                circle.id,
                fill=circle.color_template.format(
                    '00', 'ff', format(value, '02x')
                ),
            )
        canvas.after(10, color_animation, canvas, circles, values)


def main():
    root = tk.Tk()
    root.title('RGB_t.py')
    canvas = tk.Canvas(root, width=700, height=700, bg='white')
    canvas.pack()
    circles = [
        Circle(canvas.create_oval(250, 250, 450, 450), '#{2}{2}{2}'),
        Circle(canvas.create_oval(250, 25, 450, 225), '#{2}{0}{0}'),
        Circle(canvas.create_oval(250, 475, 450, 675), '#{1}{2}{2}'),
        Circle(canvas.create_oval(25, 135, 225, 335), '#{0}{2}{0}'),
        Circle(canvas.create_oval(25, 365, 225, 565), '#{2}{1}{2}'),
        Circle(canvas.create_oval(475, 135, 675, 335), '#{0}{0}{2}'),
        Circle(canvas.create_oval(475, 365, 675, 565), '#{2}{2}{1}'),
    ]
    color_animation(canvas, circles, iter(range(256)))
    root.mainloop()


if __name__ == '__main__':
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
bas_oldy
User
Beiträge: 16
Registriert: Donnerstag 23. August 2018, 20:09

Danke für eure Antworten. Werde eure Hinweise beherzigen.
Viel Grüße

bas_oldy
Antworten