Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: [OPGELOST] Een variable veranderen buiten de Class (glade)  (gelezen 2865 keer)

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
[OPGELOST] Een variable veranderen buiten de Class (glade)
« Gepost op: 2009/04/03, 13:51:09 »
Hoi,
Op het moment heb ik code geschreven voor een programma dat ik wil gaan maken. De heel erg geminimaliseerde code ziet er zo uit:
try:
    import pygtk
    pygtk.require("2.0")
    import gtk
    import gtk.glade
    import os
    import gobject

except ImportError, e:
    print("Import error. Cannot start:", e)
    sys.exit(1)

class YoutubeOgg(object):
    def __init__(self):
        self.local_path = os.path.realpath(os.path.dirname(sys.argv[0]))
        self.gladefile = os.path.join(self.local_path, 'src', "main.glade")
        self.mainWindow = gtk.glade.XML(self.gladefile, "mainWindow")

        self.lblStatus = self.mainWindow.get_widget("lblStatus")

        self.dictionary()

    def dictionary(self):
        dic = { "on_mainWindow_destroy" : self.mainWindowDestroy,
               "on_btnDownload_clicked" : self.btnDownload_clicked}
        self.mainWindow.signal_autoconnect(dic)

    def btnDownload_clicked(self, signal):
        DoeIets()

if __name__ == '__main__':
    x = YoutubeOgg()
    gtk.main()
DoeIets() importeert een module en voert het uit. Weet iemand hoe ik, vanuit de uitgevoerde class/functie (uit de module) bijvoorbeeld 'self.lblStatus' kan veranderen?
« Laatst bewerkt op: 2009/04/03, 18:55:47 door Martijn Bastiaan »

Offline charclo

  • Lid
Re: Een variable veranderen buiten de Class (glade)
« Reactie #1 Gepost op: 2009/04/03, 15:26:06 »
    def btnDownload_clicked(self, signal):
        print "Voer btnDownload_clicked uit" # Als deze tekst niet in je console verschijnt als
                                                          # je op de knop drukt heb je iets fout gedaan in je glade file
        DoeIets(self)

class DoeIets:
    def __init__(self, x):
        x.lblStatus.set_text("Schrijf hier iets")

beter is het nog om de module die je uitvoert iets te laten teruggeven en dat te gebruiken om je lblStatus te updaten

    def btnDownload_clicked(self, signal):
        print "Voer btnDownload_clicked uit" # Als deze tekst niet in je console verschijnt als
                                                          # je op de knop drukt heb je iets fout gedaan in je glade file
        d = DoeIets()
        tekstje = d.doe_iets()
        self.lblStatus.set_text(tekstje)

class DoeIets:
    def __init__(self, x):
        print "joepie"

    def doe_iets(self):
        print "doe hier iets"
        return "Het is gelukt"
« Laatst bewerkt op: 2009/04/03, 15:46:59 door charclo »
HP Pavilion dv6660eb - Intel Core 2 Duo T7250 2 GHz - 2 GB ram - Nvidia GeForce 8400M GS 128 MB --> Dualboot Ubuntu en Windows Vista
P4 2.6 GHz - 1GB ram - NVIDIA GS7600 - 20 inch Benq widescreen --> Dualboot Ubuntu en Windows XP

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: Een variable veranderen buiten de Class (glade)
« Reactie #2 Gepost op: 2009/04/03, 18:25:13 »
Geweldig! :)

Heel erg bedankt.

Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #3 Gepost op: 2009/04/03, 19:03:38 »
De oplossing hebt ge al, gewoon even wat dingetjes :).

Waarom zet ge de signal dictionary in een aparte functie? Gewoon in __init__() zetten lijkt me.

Bij een callback van een Glade widget word de widget meegegeven, niet het signaal.
Hier bijvoorbeeld:
    def btnDownload_clicked(self, signal):
signal zal niet het signaal zijn, maar wel de widget die het signaal ontvangt.
Misschien weet ge dit al, maar dan vind ik de naam wat gek gekozen, meestal is deze gewoon widget .

En een kleine tip die best handig is: in plaats van elke widget op te halen uit de Glade-file, kunt ge dit simpel doen in een lus.
for w in self.mainWindow.get_widget_prefix(''):
    name = w.get_name()
    setattr(self, name, w)
In uw voorbeeld haalt ge maar 1 widget op, maar als ge er een heleboel nodig hebt, is dit heel wat handiger.

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #4 Gepost op: 2009/04/03, 20:38:04 »
Bedankt Nunslaughter, dat is inderdaad veel makkelijker. En excuses van dat signal, wist ik zelf ook wel, maar ik dacht niet echt na toen ik het er neerzette :-[

En nog even een vraagje: als ik hetvolgende probeer (met een GtkProgressBar):
        main.pBar.set_fraction(0.1)
        time.sleep(1)
        main.pBar.set_fraction(0.2)
dan gebeurt er niks met die main.pBar.set_fraction(0.1).., ik zie zegmaar niks en na 1 seconde is het balkje ineens 20% gevuld. Moet ik het eerst flushen ofzo?

Offline charclo

  • Lid
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #5 Gepost op: 2009/04/03, 21:56:35 »
        gobject.timeout_add(1000, self.update_progress_bar)

    def update_progress_bar(self):
        main.pBar.set_fraction(self.progress)
        return false # als je hier true returned zal de functie na 1000 milliseconden opnieuw uitgevoerd worden


http://www.pygtk.org/docs/pygobject/gobject-functions.html#function-gobject--timeout-add
« Laatst bewerkt op: 2009/04/03, 22:22:50 door charclo »
HP Pavilion dv6660eb - Intel Core 2 Duo T7250 2 GHz - 2 GB ram - Nvidia GeForce 8400M GS 128 MB --> Dualboot Ubuntu en Windows Vista
P4 2.6 GHz - 1GB ram - NVIDIA GS7600 - 20 inch Benq widescreen --> Dualboot Ubuntu en Windows XP

Offline profoX

  • Lid
    • wesley
    • Lionslink
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #6 Gepost op: 2009/04/03, 22:25:00 »
dan gebeurt er niks met die main.pBar.set_fraction(0.1).., ik zie zegmaar niks en na 1 seconde is het balkje ineens 20% gevuld. Moet ik het eerst flushen ofzo?
sleep() is een blocking functie en zal de main loop van GTK+ daardoor waarschijnlijk pauzeren, waardoor de GUI niet geüpdatet kan worden. Daarom moet je iets anders gebruiken dan sleep() of de sleep() functie in een aparte thread draaien. De oplossing van charclo zou wel kunnen werken.
Human Knowledge Belongs To The World -- Antitrust (2001)
Nederlandstalige Ubuntu documentatie van Ubuntu-NL (wiki)

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #7 Gepost op: 2009/04/04, 09:50:09 »
Oké, bedankt jongens (meiden!)! =D

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #8 Gepost op: 2009/04/04, 14:03:05 »
Bah, volgende vraag. Ben ik nou zo dom of is dit gewoon ingewikkeld?

De volgende code:
    def btnDownload_clicked(self, signal):
        # Maak alles grijs
        threading.Thread(target=partial(self.grey, 0)).start()
        threading.Thread(target=partial(self.foo)).start()

    def grey(self, boolean=0):
        self.hbox1.set_sensitive(boolean)
        self.hbox2.set_sensitive(boolean)
        self.hbox3.set_sensitive(boolean)
        self.hbox5.set_sensitive(boolean)
        self.hbox6.set_sensitive(boolean)
        self.hbox7.set_sensitive(boolean)
        self.hbox8.set_sensitive(boolean)
        self.hbox9.set_sensitive(boolean)

    def foo(self):
        x = YouTube.YouTube()
        dic = x.parseURL(self.entryURL.get_text())
        if dic == False:
            self.lblError.set_markup('<b><span foreground="red">Fout. De gegeven URL is niet juist.</span></b>')
        else:
            print(dic)
            x.download(dic, self)
            self.lblError.set_markup('<b><span foreground="#00a204">Geslaagd!</span></b>')
            self.grey(1)
    def download(self, dic, main):
        """blabla"""
        main.pBar.set_text('Controleren..')
       
        print(0)
Alles werkt, tot x.download(dic, self)! Dan stop het programma gewoon, pas als ik de GUI afsluit komt er in de terminal '0' te staan..

Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #9 Gepost op: 2009/04/04, 14:10:30 »
Om met een progressbar in PyGTK te werken hebt ge threads nodig.

Ik heb eens een programma geschreven wat progressbars gebrukt, ik zal het eens even uit de code zoeken en hier posten.

Offline profoX

  • Lid
    • wesley
    • Lionslink
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #10 Gepost op: 2009/04/04, 14:19:36 »
Om met een progressbar in PyGTK te werken hebt ge threads nodig.
Vreemd. Ben je daar zeker van? Dat zou wel er inefficiënt en ongemakkelijk zijn dan. Volgens mij kan het ook 'gewoon' non-threaded (in andere toolkits zoals Qt gaat het tenslotte toch ook)
Human Knowledge Belongs To The World -- Antitrust (2001)
Nederlandstalige Ubuntu documentatie van Ubuntu-NL (wiki)

Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #11 Gepost op: 2009/04/04, 14:37:09 »
Dan heb ik misschien het verkeerde adves gekregen toen ik ermee begon. Ge kunt geen operatie uitvoeren (een download bijvoorbeeld) en tegelijkertijd de progressbar laten bewegen. De GUI zal geblokkeerd worden tot de download compleet is.

Nuja, dit is wat ik ervan gemaakt heb (niet getest!):
import time
import thread

def btnDownload_clicked(self, widget):
    self.grey(0)
    self.foo()

def grey(self, boolean=0):
    self.hbox1.set_sensitive(boolean)
    self.hbox2.set_sensitive(boolean)
    self.hbox3.set_sensitive(boolean)
    self.hbox5.set_sensitive(boolean)
    self.hbox6.set_sensitive(boolean)
    self.hbox7.set_sensitive(boolean)
    self.hbox8.set_sensitive(boolean)
    self.hbox9.set_sensitive(boolean)

def foo(self):
    x = YouTube.YouTube()
    dic = x.parseURL(self.entryURL.get_text())
    if dic == False:
        self.lblError.set_markup('<b><span foreground="red">Fout. De gegeven URL is niet juist.</span></b>')
    else:
        print(dic)
        lock = thread.allocate_lock()
        lock.acquire()
        t = thread.start_new_thread(x.download, (lock, dic))
        self.pBar.set_text("Controleren...")
        while lock.locked():
            self.pBar.pulse()
            while gtk.events_pending():
                gtk.main_iteration()
            time.sleep(0.05)
        self.pBar.set_text("Done!")
        self.lblError.set_markup('<b><span foreground="#00a204">Geslaagd!</span></b>')
        self.grey(1)
def download(lock, dic):

    # Download hier

    lock.release()

Offline profoX

  • Lid
    • wesley
    • Lionslink
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #12 Gepost op: 2009/04/04, 18:32:18 »
Dan heb ik misschien het verkeerde adves gekregen toen ik ermee begon. Ge kunt geen operatie uitvoeren (een download bijvoorbeeld) en tegelijkertijd de progressbar laten bewegen. De GUI zal geblokkeerd worden tot de download compleet is.
Dat klopt, omdat de main loop dan geblokkeerd wordt. Maar is er geen eventbased downloadsysteem in GTK+ of Python? In Qt zou je hiervoor bijvoorbeeld QHttp kunnen gebruiken zodat je niet hoeft te klooien met threads.
Human Knowledge Belongs To The World -- Antitrust (2001)
Nederlandstalige Ubuntu documentatie van Ubuntu-NL (wiki)

Offline charclo

  • Lid
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #13 Gepost op: 2009/04/04, 18:49:14 »
Dan heb ik misschien het verkeerde adves gekregen toen ik ermee begon. Ge kunt geen operatie uitvoeren (een download bijvoorbeeld) en tegelijkertijd de progressbar laten bewegen. De GUI zal geblokkeerd worden tot de download compleet is.

Nuja, dit is wat ik ervan gemaakt heb (niet getest!):
import time
import thread

def btnDownload_clicked(self, widget):
    self.grey(0)
    self.foo()

def grey(self, boolean=0):
    self.hbox1.set_sensitive(boolean)
    self.hbox2.set_sensitive(boolean)
    self.hbox3.set_sensitive(boolean)
    self.hbox5.set_sensitive(boolean)
    self.hbox6.set_sensitive(boolean)
    self.hbox7.set_sensitive(boolean)
    self.hbox8.set_sensitive(boolean)
    self.hbox9.set_sensitive(boolean)

def foo(self):
    x = YouTube.YouTube()
    dic = x.parseURL(self.entryURL.get_text())
    if dic == False:
        self.lblError.set_markup('<b><span foreground="red">Fout. De gegeven URL is niet juist.</span></b>')
    else:
        print(dic)
        lock = thread.allocate_lock()
        lock.acquire()
        t = thread.start_new_thread(x.download, (lock, dic))
        self.pBar.set_text("Controleren...")
        while lock.locked():
            self.pBar.pulse()
            while gtk.events_pending():
                gtk.main_iteration()
            time.sleep(0.05)
        self.pBar.set_text("Done!")
        self.lblError.set_markup('<b><span foreground="#00a204">Geslaagd!</span></b>')
        self.grey(1)
def download(lock, dic):

    # Download hier

    lock.release()

Dit lijkt me heel ingewikkeld. Normaal gezien moet je hier terug gobject.timeout_add() voor gebruiken maar deze keer met een callback.
Ik zal hier later een voorbeeldje over posten als ik iets meer tijd heb.
HP Pavilion dv6660eb - Intel Core 2 Duo T7250 2 GHz - 2 GB ram - Nvidia GeForce 8400M GS 128 MB --> Dualboot Ubuntu en Windows Vista
P4 2.6 GHz - 1GB ram - NVIDIA GS7600 - 20 inch Benq widescreen --> Dualboot Ubuntu en Windows XP

Offline charclo

  • Lid
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #14 Gepost op: 2009/04/04, 19:48:25 »
Heb je hier een stuk uit weggelaten voor je het hier gepost hebt? Het lijkt me raar dat hij hierop blokkeert.

    def download(self, dic, main):
        """blabla"""
        main.pBar.set_text('Controleren..')
       
        print(0)

Waar in je geposte code wordt er effectief iets gedownload?

En als je met threads wil werken zal de classe YouTube.YouTube waarschijnlijk gewoon van Thread moeten inheriten. Hier vindt je er een goed voorbeeld van http://www.wellho.net/solutions/python-python-threads-a-first-example.html
« Laatst bewerkt op: 2009/04/04, 20:37:26 door charclo »
HP Pavilion dv6660eb - Intel Core 2 Duo T7250 2 GHz - 2 GB ram - Nvidia GeForce 8400M GS 128 MB --> Dualboot Ubuntu en Windows Vista
P4 2.6 GHz - 1GB ram - NVIDIA GS7600 - 20 inch Benq widescreen --> Dualboot Ubuntu en Windows XP

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #15 Gepost op: 2009/04/05, 10:08:43 »
Heb je hier een stuk uit weggelaten voor je het hier gepost hebt? Het lijkt me raar dat hij hierop blokkeert.
Nee, niet eens, daarom is het ook zo vreemd. Ik ga nu de suggesties proberen.

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #16 Gepost op: 2009/04/05, 10:17:06 »
De suggestie van Nunslaughter werkt. Nu moet ik alleen nog even uitvissen hoe ik er een echte progressbar van maak, maar dat lijkt me niet zo moeilijk. Bedankt.

Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #17 Gepost op: 2009/04/05, 11:22:48 »
Dan hebt ge de reporthook nodig van urllib.urlretrieve().

    def download_file(self, url, local):
        urllib.urlretrieve(url, local, self.update_progress)

    def update_progress(self, blocks, block_size, total_size):
        blocksdone = float(blocks * block_size) / total_size
        percentage = int(blocksdone*100)
        self.progressbar.set_text(str(percentage)+" %")
        if blocksdone < 1:
            self.progressbar.set_fraction(blocksdone)

Offline MartijnB

  • Lid
    • http://www.mbastiaan.nl
Re: [OPGELOST] Een variable veranderen buiten de Class (glade)
« Reactie #18 Gepost op: 2009/04/05, 13:59:59 »
Ok! Dat is heel handig, bedankt.