for event schleife

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

Hallo,

ich bin dabei ein etwas komplexeres Programm zu schreiben, mit dem ich eine Tello Drohne steuern will.

Meine Idee ist folgende:
ich habe mein main Programm, in dem ich die ganzen Unterfunktionen aus anderen Skripts aus diesem Ordner aufrufe. Das mache ich aus Übersichtlichkeitsgründen. Im main gibt es damit nur die main() Funktion, in der erst einige Werte initialisiert werden und dann die while-Schleife betreten wird. Zunächst werden die Funktiionen aufgerufen, dann zum Schluss die

Code: Alles auswählen

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                
Ausdrücke.

Nun möchte ich eine Fotoabspeicherfunktion implementieren. Das Bildmachen an sich ist kein Problem, nur möchte ich, dass nach Bildschuss eine Textbox erscheint, in die der Nutzer den Namen des BIldes eintragen kann. In diesem Zustand ist die Variable steuerung_aktive == Falsch.
Daran scheitere ich.
Ich nutze als Hilfe https://www.youtube.com/watch?v=Rvcyf4HsWiw&t=519s , sowie https://www.codegrepper.com/code-exampl ... hon+pygame


meine Klasse textBox sieht so aus:

Code: Alles auswählen

class textBox():
    def __init__(self, x, y, breite, hoehe, buttonfarbe, text_input, textfarbe, schriftgroesse):
        self.x = x
        self.y = y
        self.breite = breite
        self.hoehe = hoehe
        self.buttonfarbe = buttonfarbe
        self.text_input = text_input
        self.textfarbe = textfarbe
        self.schriftgroesse = schriftgroesse




    def zeichne_button(self, SCREEN, event):
        rechteckiger_button = Rect(self.x, self.y, self.breite, self.hoehe)


        if event.type == pygame.KEYDOWN:
            if steuerung.ist_taste_gedrueckt("BACKSPACE"):
                self.text_input = self.text_input[:-1]
            else:
                self.text_input += event.unicode

        pygame.draw.rect(SCREEN, self.buttonfarbe, rechteckiger_button)





        text_als_button = self.schriftgroesse.render(self.text_input, True, self.textfarbe)
        #text_laenge = text_als_button.get_width()
        SCREEN.blit(text_als_button, (self.x, self.y))
        
ich baue zeichne_button folgend ein:

Code: Alles auswählen

        # Fensterevents
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                run = False
            if steuerung_aktiv == False:   
                button_modul.text_box.zeichne_button(SCREEN, event)
                
an sich funktioniert es, ich sehe die Box im Fenster und ich kann Text eintippen, ich sehe die Box jedoch nur wenn ich meine Maus bewege oder schreibe für den Bruchteil einer Sekunde. Danach ist sie sofort wieder weg und ich sehe das leere pygame Fenster. Wo ist hier mein Fehler? Wie könnte ich es besser machen?


Danke!
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

G-Rizzle hat geschrieben: Donnerstag 1. April 2021, 13:38 Hallo,

ich bin dabei ein etwas komplexeres Programm zu schreiben, mit dem ich eine Tello Drohne steuern will.

Meine Idee ist folgende:
ich habe mein main Programm, in dem ich die ganzen Unterfunktionen aus anderen Skripts aus diesem Ordner aufrufe. Das mache ich aus Übersichtlichkeitsgründen. Im main gibt es damit nur die main() Funktion, in der erst einige Werte initialisiert werden und dann die while-Schleife betreten wird. Zunächst werden die Funktiionen aufgerufen, dann zum Schluss die

Code: Alles auswählen

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                
Ausdrücke.

Nun möchte ich eine Fotoabspeicherfunktion implementieren. Das Bildmachen an sich ist kein Problem, nur möchte ich, dass nach Bildschuss eine Textbox erscheint, in die der Nutzer den Namen des BIldes eintragen kann. In diesem Zustand ist die Variable steuerung_aktive == Falsch.
Daran scheitere ich.
Ich nutze als Hilfe https://www.youtube.com/watch?v=Rvcyf4HsWiw&t=519s , sowie https://www.codegrepper.com/code-exampl ... hon+pygame


meine Klasse textBox sieht so aus:

Code: Alles auswählen

class textBox():
    def __init__(self, x, y, breite, hoehe, buttonfarbe, text_input, textfarbe, schriftgroesse):
        self.x = x
        self.y = y
        self.breite = breite
        self.hoehe = hoehe
        self.buttonfarbe = buttonfarbe
        self.text_input = text_input
        self.textfarbe = textfarbe
        self.schriftgroesse = schriftgroesse




    def zeichne_button(self, SCREEN, event):
        rechteckiger_button = Rect(self.x, self.y, self.breite, self.hoehe)


        if event.type == pygame.KEYDOWN:
            if steuerung.ist_taste_gedrueckt("BACKSPACE"):
                self.text_input = self.text_input[:-1]
            else:
                self.text_input += event.unicode

        pygame.draw.rect(SCREEN, self.buttonfarbe, rechteckiger_button)





        text_als_button = self.schriftgroesse.render(self.text_input, True, self.textfarbe)
        #text_laenge = text_als_button.get_width()
        SCREEN.blit(text_als_button, (self.x, self.y))
        
ich baue die Funktion zeichne_button folgend in die for event Schleife in der main() Funktion ein:

Code: Alles auswählen

        # Fensterevents
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                run = False
            if steuerung_aktiv == False:   
                button_modul.text_box.zeichne_button(SCREEN, event)
                
an sich funktioniert es, ich sehe die Box im Fenster und ich kann Text eintippen, ich sehe die Box jedoch nur wenn ich meine Maus bewege oder schreibe für den Bruchteil einer Sekunde. Danach ist sie sofort wieder weg und ich sehe das leere pygame Fenster. Wo ist hier mein Fehler? Wie könnte ich es besser machen?


Danke!
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Klassen schreibt man mit großem Anfangsbuchstaben `TextBox` und Variablennamen schreibt man komplett klein `screen`.

Du brauchst, wie im anderen Thread ja schon gezeigt, zwei Methoden, eine zum Abarbeiten eines Events, und eine zum Zeichnen.

Code: Alles auswählen

class TextBox():
    def __init__(self, x, y, breite, hoehe, buttonfarbe, text_input, textfarbe, schriftgroesse):
        self.x = x
        self.y = y
        self.breite = breite
        self.hoehe = hoehe
        self.buttonfarbe = buttonfarbe
        self.text_input = text_input
        self.textfarbe = textfarbe
        self.schriftgroesse = schriftgroesse

    def process_event(self, event):
        if event.type == pygame.KEYDOWN:
            if steuerung.ist_taste_gedrueckt("BACKSPACE"):
                self.text_input = self.text_input[:-1]
            else:
                self.text_input += event.unicode

    def zeichne_button(self, screen):
        rechteckiger_button = Rect(self.x, self.y, self.breite, self.hoehe)
        pygame.draw.rect(screen, self.buttonfarbe, rechteckiger_button)
        text_als_button = self.schriftgroesse.render(self.text_input, True, self.textfarbe)
        screen.blit(text_als_button, (self.x, self.y))
Und entscheidend ist ja, was sonst noch in Deiner Mainloop passiert. Da übermalst Du wahrscheinlich Deine Box wieder. Den Code brauchen wir auch noch.
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

ahhh. ich verstehe deinen post im anderen thread jetzt erst richtig. ich tüftel mal noch ne weile und melde mich ggfs. nochmal. danke!
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

okay, leider immnoch selbiges Problem. Klasse TextBox habe ich entsprechend angepasst. Zur "variable" screen: Dachte das wäre eine Konstante? Wird ja im Ursprung initialisiert und dann nicht mehr verändert? Verändere ich dann auf jeden Fall noch ggfs. nach deiner Antwort.


hier mein Mainloop: Kurze Erklärung: Die Drohne hat 3 Zustände, disconnected, connecting, connected. Das wird über die Variable "connected" festgehalten.

Zustand 1, disconnected: Variable connected == "disconnected". Im Fenster erscheinen die Buttons "disconnected", daneben ein interaktiver "connect" button, der bei klick entsprechende Drohnenverbindung versucht und Variable connected in "connecting" verändert. klappt das nicht springt die connect Variable wieder in den "disconnected" Zustand, ansonsten wird sie zu "connected".

Code: Alles auswählen

   # Schleifeninitialierung
    run = True
    durchlauf = 0



    # Schleife
    while run:
        # --- Fensteraufbau ---
        # Hintergrund
        SCREEN.fill(farben.dunkelblau2)
        button_modul.oberer_balken.zeichne_button(SCREEN)





        # Disconnected
        if connected == 'disconnected':

            # statischer disconnected Button
            button_modul.disconnected_button.zeichne_button(SCREEN)



            # interaktiver 'verbinden' button
            button_modul.direktverbinden_button.zeichne_button(SCREEN, button_modul.direktverbinden_button.geklickt, button_modul.direktverbinden_button.action)

            # Wenn 'Verbinden' Button geklickt wird
            if button_modul.direktverbinden_button.action == True:
                connected = 'connecting'
                button_modul.direktverbinden_button.action = False


        # Verbindung aktiviert
        elif connected == 'connecting':
            # statischer 'Verbinden...' Button
            button_modul.verbinden_button.zeichne_button(SCREEN)


            if zum_ersten_mal_verbinden == True:
                zum_ersten_mal_verbinden = False
            else:
                verbinden_return = dronen_funktionen.verbinden(drone)
                zum_ersten_mal_verbinden = True


                if verbinden_return == True:
                    connected = 'connected'


                else:
                    connected = 'disconnected'




        # Verbunden, Direkt
        elif connected == 'connected':
            #steuerung_aktiv = True


            # connected-button zeichnen
            button_modul.direktverbunden_button.zeichne_button(SCREEN)



            # alle 1000 Durchläufe:
            # Verbindungscheck

            if durchlauf == 0:
                connected = dronen_funktionen.verbindung_checken(drone)


            # Batterieanzeige
            batterieanzeige_return = dronen_funktionen.batterie_checken(drone)
            batteriebutton = batterieanzeige_return['batteriebutton']

            batteriebutton.zeichne_button(SCREEN)




            # Videostream
            videostreamen_return = dronen_funktionen.videostreamen(drone)
            SCREEN.blit(videostreamen_return['surfed_stream'], (initialisieren_return['FENSTER_BREITE'] / 2 - videostreamen_return['STREAM_BREITE'] / 2 , 30))



            # steuerung
            steuern_return = steuerung.steuern(drone, steuern_return['drueckzeiten'], steuern_return['sekundenzaehler'])










        # Fensterevents
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                run = False
            
            button_modul.text_box.process_event(event)
            button_modul.text_box.zeichne_button(SCREEN)



        # --- Update ---

        # Zählvariable
        durchlauf += 1
        if durchlauf == 1000:
            durchlauf = 0
        else:
            pass



        # Refresh

        pygame.display.update()



wie gesagt, an sich erscheint die Textbox, allerdings nur für den Bruchteil einer Sekunde falls sich irgendwas im Fenster ändert (z.b. wenn ich tippe oder maus bewege).
Benutzeravatar
__blackjack__
User
Beiträge: 13064
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@G-Rizzle: Screen ist keine Konstante. Das ist ein Objekt mit Zustand der vom Programm geändert wird.

Die Aufteilung auf Module sieht auch so aus als wäre da noch mehr globaler Zustand. Was da so im `button_modul` ist sollte da nicht einfach so auf Modulebene vorhanden sein. Das ist auch ein bisschen schräg ausgerechnet alle Buttons in ein Modul zu stecken. Das ist so als würde eine Bibliothek die Bücher nach Grösse und Einbandfarben ordnen statt nach Fachrichtung und alphabetisch.

Dann hängt man nicht einen `_return`-Suffix an Namen nur weil die an einen Rückgabewert von einem Aufruf gebunden werden. Was soll das denn? Das ist doch völlig egal ob so ein Wert aus einem Literal, einem Operator, oder einem Aufruf stammt.

Es gibt da anscheinend auch Rückgabewerte die Wörterbücher sind die offenbar als Objekte herhalten. Da sollte man Objekte verwenden, beispielsweise von einem mit `collections.namedtuple()` erstellten Datentyp.

In Modulnamen sollte weder der Teil `modul` vorkommen noch `funktionen`.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

merci. setze ich gleich mal um. auf das eigentliche problem mit der verschwindenden textbox hat das allerdings keinen einfluss oder?
G-Rizzle
User
Beiträge: 90
Registriert: Donnerstag 18. Februar 2021, 12:26

ich habe die lösung: fehler war die funktion zeichne_button(screen) mit in die for event in pygame.event.get() schleife zu packen. ich habe die jetzt zu den anderen button_zeichnen() funktionen gesetzt und dann passt alles
Antworten