Fórum Ubuntu CZ/SK
Ubuntu pro osobní počítače => Software => Příkazový řádek a programování pro GNU/Linux => Téma založeno: Kamil Hanus 12 Října 2011, 18:23:40
-
Zdravím,
pracuji na jedné aplikaci v Pythonu s využitím pyGTK a potřeboval bych poradit se zřejmě banální věcí. Rád bych měl Label pole, ve které by se postupně zleva doprava vysunul text. Bohužel moc znalostí o využití více vláken nemám a níže zobrazený kód mi nefunguje. V podstatě můj problém je takový, že namísto zobrazení okna a následném "vysunutí" textu se neděje nic, dokud neskončí cyklus, který měl zobrazovat text a až potom se zobrazí samotné okno (s již finálně zobrazeným textem).
Mohli byste mi prosím někdo poradit, co dělám špatně? Díky :)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import threading
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
import gtk.glade
except:
sys.exit(1)
gtk.gdk.threads_init()
NUM_THREADS = 2
class CT24bar():
def __init__(self, threads=None):
self.gladefile = "main_vzhled.glade"
self.wTree = gtk.glade.XML(self.gladefile)
self.window = self.wTree.get_widget("window1")
color = gtk.gdk.color_parse('#FFFFFF')
self.window.modify_bg(gtk.STATE_NORMAL, color)
self.threads = []
self.text = self.wTree.get_widget("label2")
self.threads.append(ZmenText(self.text))
self.window.show_all()
def run(self):
gtk.main()
class ZmenText(threading.Thread):
def __init__(self, text_label):
threading.Thread.__init__(self)
self.text=text_label
gtk.gdk.threads_enter()
text="Postupně zobrazený text"
tmp=""
for i in text:
tmp = tmp + i
self.text.set_label(tmp)
time.sleep(0.05)
gtk.gdk.threads_leave()
if __name__ == "__main__" :
application = CT24bar()
for t in application.threads:
t.start()
gtk.gdk.threads_enter()
gtk.main()
gtk.gdk.threads_leave()
-
Jestli při tom vykreslování nepotřebuješ opravdu dělat ještě něco jiného, můžeš zapomenout na thready a stačilo by jen v každém průběhu smyčky nechat překreslit GTK změny, protože jinak dokud nepředá callback řízení zpět hlavní smyčce, nic se nekreslí.
while gtk.events_pending():
gtk.main_iteration_do(False)
Další možností je pak udělat si generátor, který bude volat callback ve zvoleném intervalu a tak je možné 'současně' dělat i jiné věci, nemusí se čekat ve sleepu. Zkrátka se ten cyklus rozloží do několika volání.
A ještě odkaz: http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--timeout-add (http://www.pygtk.org/pygtk2reference/gobject-functions.html#function-gobject--timeout-add)
-
Díky, ten gobject vypadá nadějně. Nicméně i když se mi ve výpisu v terminálu zobrazují znaky postupně, v okně se vše zobrazí až najednou. Což mi přijde divné, protože výpis proměnné mám daný až po nastavení labelu.
def __init__(self, text_label):
def sleeper(tmp):
time.sleep(0.01)
self.text.set_label(tmp)
print "0 - "+tmp
threading.Thread.__init__(self)
self.text=text_label
text="Postupně zobrazený text"
tmp=""
for i in text:
tmp = tmp + i
print tmp
gobject.timeout_add(10, sleeper, tmp)
-
Tos špatně pochopil ten gobject, tim založíš generátor, který bude ve zvoleném intervalu volat zadaný callback (dokud mu nevrátíš False). Tak jak jsi to použil, k tomu je právě ta první varianta, kterou jsem ti dal. Hlavně ani v jednom případě nepotřebuješ thread. Zkrátka:
for i in text:
tmp = tmp + i
self.text.set_label(tmp)
while gtk.events_pending():
gtk.main_iteration_do(False)
time.sleep(0.05)
-
Tak jsem to zkoušel a nefungovalo. Problém byl zřejmě v použití Threadu, bez něj o jede jak má :) Díky moc! K+
-
Vzpoměl jsem si na toto vlákno, když jsem dnes začal psát k tomuto tématu na blog, tak to sem přihodim, kdyby se to hodilo. Je to už pro GTK+ 3, ale vlastně je to až na strukturu knihovny stejné i v GTK+ 2.
PyGObject - Aktualizace GUI z callbacku, časovače, i vlákna (http://gdhnotes.blogspot.cz/2012/11/pygobject-aktualizace-gui-z-callbacku.html)