Fenster laufend aktualisieren

Fragen zu Tkinter.
Antworten
Üpsilon
User
Beiträge: 225
Registriert: Samstag 15. September 2012, 19:23

Hallo mal wieder.
Kann mir jemand sagen, wie ich mache, dass WÄHREND mein GUI-Programm läuft, ständig die gleichen Anweisungen ausgeführt werden? Einfach eine Schleife ins Programm reinbasteln scheint ja nicht so ganz die empfohlene Strategie zu sein und funktioniert bei mir auch gar nicht.
Wenn daraus jez nicht ersichtlich geworden ist, was ich meine, kann ich gerne noch meinen Quellcode posten, aber ich wollte hier nicht rumspämmen. :wink:
Danke und Lg Y.

Edit (23. 6. 16:53) : Thread-Titel geändert
Zuletzt geändert von Üpsilon am Montag 23. Juni 2014, 15:54, insgesamt 1-mal geändert.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Einfach einen Thread starten. Sei aber vorsichtig, ein Thread darf nicht einfach Elemente der GUI verändern, das geht nicht gut aus. Zum Thema Threads und GUIs gibt es hier im Forum aber genug, einfach mal ein wenig suchen.
Das Leben ist wie ein Tennisball.
Üpsilon
User
Beiträge: 225
Registriert: Samstag 15. September 2012, 19:23

Erstmal danke für die schnelle Antwort.
EyDu hat geschrieben:ein Thread darf nicht einfach Elemente der GUI verändern.
Menno. Ich will aber!!! :cry: :cry: :cry: :wink:

Nein, ich meinte eher, dass laufend das Fenster aktualisiert wird. Ich glaube, ich ändere mal den Titel dieses Themas.
PS: Die angebotene Summe ist beachtlich.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Was genau willst du denn machen, deine neue Beschreibung ist ja noch viel allgemeiner geworden. Prinzipiell kommen mehrere Ansätze in Frage. Wie sieht denn dein ganz konkretes Problem aus?
Das Leben ist wie ein Tennisball.
Üpsilon
User
Beiträge: 225
Registriert: Samstag 15. September 2012, 19:23

Ist inzwischen relativ egal, weil ich es jetzt hinbekommen habe. ^^

Mein Programm sollte mit einem numerischen Verfahren Pi annähern und die Zwischenergebnisse in einer GUI anzeigen, und das nach jedem Näherungsschritt. Und die Berechnung soll man auch pausieren können.
Ich hab das jetzt so gemacht, dass mein Eventhandler sich nach jedem Schritt rekursiv selbst aufruft. Aber egal, danke.
PS: Die angebotene Summe ist beachtlich.
BlackJack

@Üpsilon: Ich hoffe mal der Eventhandler macht das nicht tatsächlich rekursiv, denn Schleifen als Rekursionen ausdrücken funktioniert in Python nicht wirklich, wie eigentlich in allen Programmiersprachen nicht in denen die Sprachdefinition keine „tail call optimization” garantiert.
Üpsilon
User
Beiträge: 225
Registriert: Samstag 15. September 2012, 19:23

BlackJack hat geschrieben:@Üpsilon: Ich hoffe mal der Eventhandler macht das nicht tatsächlich rekursiv, denn Schleifen als Rekursionen ausdrücken funktioniert in Python nicht wirklich...
Nee, da ist der schon nach 100 Durchläufen abgestürzt. Ich benutze für die Rekursion fenster.after(), wobei fenster ein tkinter.Tk() ist.
PS: Die angebotene Summe ist beachtlich.
Üpsilon
User
Beiträge: 225
Registriert: Samstag 15. September 2012, 19:23

Falls es jemanden interessiert, ich klatsch hier mal den Quellcode rein. In der Methode pi_naehern wird zufällig ein Punkt generiert, dann wird mit dem Pythagoras geguckt, ob der im gedachten Viertel-Kreis drin ist, und dann wird mit Hilfe der "Trefferquote" überlegt, wie groß der Kreis denn ungefähr ist und wie groß Pi folglich sein muss. Der Rest ist für die GUI zuständig.

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import tkinter as tk
from random import random

class Pi_Rechner:
    
    def __init__(self, update_schritt=100, wartezeit=500):
        self.punkte_gesetzt = 0
        self.punkte_im_kreis = 0
        self.laeuft = False
        self.update_schritt = update_schritt
        self.wartezeit = wartezeit
        self.init_fenster()

    def init_fenster(self):
        self.fenster = tk.Tk()
        self.fenster.geometry("400x150")
        self.fenster.title("Pi nähern")
        self.gesetzt_label = tk.Label(self.fenster)
        self.im_kreis_label = tk.Label(self.fenster)
        self.pi_label = tk.Label(self.fenster)
        for label in (self.gesetzt_label, self.im_kreis_label, self.pi_label):
            label.config(font="Arial 14")
            label.pack()
        self.startstop_button = tk.Button(self.fenster, text="Start", command=self.umschalten)
        self.startstop_button.pack()

    def umschalten(self):
        self.laeuft = not self.laeuft
        button_text = "Pause" if self.laeuft else "Weiter"
        self.startstop_button.configure(text=button_text)
        if self.laeuft:
            self.durchlauf()

    def pi_naehern(self):
        self.punkte_gesetzt += 1
        x, y = random(), random()
        abstand = (x**2 + y**2) ** 0.5
        if abstand <= 1:
            self.punkte_im_kreis += 1

    def gui_aktualisieren(self):
        self.gesetzt_label.configure(text = "Punkte gesetzt: %i" %self.punkte_gesetzt)
        self.im_kreis_label.configure(text = "Punkte im Viertelkreis: %i" %self.punkte_im_kreis)
        self.pi_label.configure(text = "π = 4*%i/%i = %f"
                                %(self.punkte_im_kreis, self.punkte_gesetzt,
                                  4 * self.punkte_im_kreis / self.punkte_gesetzt))

    def durchlauf(self):
        self.pi_naehern()
        if self.punkte_gesetzt % self.update_schritt == 0:
            self.gui_aktualisieren()
            self.fenster.after(self.wartezeit, self.durchlauf)
        elif self.laeuft:
            self.fenster.after(0, self.durchlauf)

pi_rechner = Pi_Rechner(10000, 1)
Ich weiß, es ist nicht der Event-Handler, der sich rekursiv aufruft. Aber so was ähnliches! ^^

Edit (19:10) : kleinen Fehler in umschalten() korrigiert.
PS: Die angebotene Summe ist beachtlich.
BlackJack

@Üpsilon: Das Programm beendet sich bei mir sofort wieder. Da fehlt ein Aufruf der Tk-Hauptschleife damit das Programm dauerhaft läuft.
Antworten