veränderten text in gtk.TextView-Element anzeigen

Programmierung für GNOME und GTK+, GUI-Erstellung mit Glade.
Antworten
Myra
User
Beiträge: 3
Registriert: Montag 21. Mai 2012, 20:46

Hi,
ich möchte in einer Funktion den Text eines gtk.TextView - Elements ändern,
den neuen Text kurz anzeigen lassen
und dann nach einer kurzen Wartezeit den Text endgültig ändern.

Was ich nicht hinkriege, ist dass die erste Änderung auch angezeigt wird.
Die Anzeige wird erst aktualisiert wenn die 'Text-Änder-Funktion' sich beendet hat.

Hier mal etwas Source-Code um zu zeigen was ich meine:
es geht eigentlich nur um die kleine Funktion change_text():

Code: Alles auswählen

#!/usr/bin/env python

import pygtk
pygtk.require('2.0')
import gtk
import time

class TextViewExample:
    def change_text(self, widget):
        self.textbuffer.set_text("erster Text")
        """Jetzt soll der neue Text fuer eine Sekunde angezeigt werden, was aber NICHT funktioniert"""
        #self.sw.show()
        #self.textview.show()
        #self.window.show()
        time.sleep(1)
        """Jetzt wird der Text nochmal gaendert"""
        self.textbuffer.set_text("zweiter Text")

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_resizable(True)  
        self.window.set_title("TextView Beispiel")
        self.window.set_border_width(0)
        box1 = gtk.VBox(False, 0)
        self.window.add(box1)
        box1.show()
        box2 = gtk.VBox(False, 10)
        box2.set_border_width(10)
        box1.pack_start(box2, True, True, 0)
        box2.show()
        self.sw = gtk.ScrolledWindow()
        self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.textview = gtk.TextView()
        self.textbuffer = self.textview.get_buffer()
        self.sw.add(self.textview)
        self.sw.show()
        self.textview.show()
        box2.pack_start(self.sw)
        hbox = gtk.HButtonBox()
        box2.pack_start(hbox, False, False, 0)
        hbox.show()
        vbox = gtk.VBox()
        vbox.show()
        hbox.pack_start(vbox, False, False, 0)
        button = gtk.Button("change text")
        button.connect("clicked", self.change_text)
        box2.pack_start(button, True, True, 0)
        button.set_flags(gtk.CAN_DEFAULT)
        button.grab_default()
        button.show()
        self.window.show()

def main():
    gtk.main()
    return 0       

if __name__ == "__main__":
    TextViewExample()
    main()
Würde mich freuen wenn mir da jemand helfen könnte.

Gruß
myra
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hast du da mittlerweile eine Lösung bzw. die Ursache dafür gefunden?

button.connect("clicked", self.change_text)

Hier noch ma ein Beispiel, es wir nur der letzte "self.textbuffer.set_text" gesetzt.

Code: Alles auswählen

    def change_text(self, widget):
        self.textbuffer.set_text("erster Text")
        time.sleep(0.2)
        self.textbuffer.set_text("zweiter Text")
        time.sleep(0.2)
        self.textbuffer.set_text("aber nur ich werde angezeigt ")
BlackJack

@martinjo: Die GUI zeigt Veränderungen erst an wenn die GUI-Hauptschleife wieder die Kontrolle hat, also wenn die Methode zuende ist und dorthin zurück kehrt. Darum darf man in Methoden die von der Hauptschleife aufgerufen werden auch nichts machen was länger dauert, denn für die Laufzeit der Methode „friert” die GUI-Anzeige ein. GUI-Toolkits haben für den hier gewünschten Fall üblicherweise eine Methode um Funktionen oder Methoden zeitverzögert aufrufen zu lassen. Vorgehensweise wäre also den Text zu ändern und eine Funktion zu registrieren die 0,2s aufgerufen werden soll um den Text erneut zu ändern. Gtk hat dafür die `timeout_add()`-Funktion (Name ist anhand des Namens der Funktion in der `libglib` geraten).
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Danke :D
Benutzeravatar
diesch
User
Beiträge: 80
Registriert: Dienstag 14. April 2009, 13:36
Wohnort: Brandenburg a.d. Havel
Kontaktdaten:

Wenn der Benutzer innerhalb der Wartezeit nicht mit der GUI arbeiten können muss, reicht es, vor der Pause

Code: Alles auswählen

while Gtk.events_pending():
    Gtk.main_iteration()
aufzurufen.
http://www.florian-diesch.de
BlackJack

@diesch: Dann funktioniert aber die komplette GUI- und Ereignisverwaltung während der Wartezeit nicht. Das Fenster wird nicht neu gezeichnet wenn irgend etwas darüber gezeichnet wurde, zum Beispiel Benachrichtigungen oder bei bestimmten Systemen kann selbst der Mauszeiger ”Spuren” im Fenster hinterlassen. Und wenn das Programm die Ereignisverwaltung zum Beispiel auch für I/O-Aufgaben verwendet, dann werden die auch so lange blockiert.
Benutzeravatar
diesch
User
Beiträge: 80
Registriert: Dienstag 14. April 2009, 13:36
Wohnort: Brandenburg a.d. Havel
Kontaktdaten:

Ja. Ob das akzeptabel oder sogar erwünscht ist, hängt vom Programm ab.

Mit GLib.timeout_add kann der Code unübersichtlicher und fehleranfälliger werden, weil es schwerer nachzuvollziehen ist, in welcher Reihenfolge Dinge passieren.
http://www.florian-diesch.de
Antworten