Seite 1 von 1

Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 15:14
von Üpsilon
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

Re: Irgendeinen Befehl STÄNDIG ausführen

Verfasst: Montag 23. Juni 2014, 15:22
von EyDu
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.

Re: Irgendeinen Befehl STÄNDIG ausführen

Verfasst: Montag 23. Juni 2014, 15:52
von Üpsilon
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.

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 16:00
von EyDu
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?

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 17:12
von Üpsilon
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.

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 17:20
von 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.

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 17:28
von Üpsilon
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.

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 17:57
von Üpsilon
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.

Re: Fenster laufend aktualisieren

Verfasst: Montag 23. Juni 2014, 22:16
von BlackJack
@Üpsilon: Das Programm beendet sich bei mir sofort wieder. Da fehlt ein Aufruf der Tk-Hauptschleife damit das Programm dauerhaft läuft.