Sida 1 av 1

Enkelt GUI: rita grafer, hur uppdatera?

Postat: 08 okt 2008, 12:51
av ai
Hejhej,
jag håller på med ett litet program som ska rita upp några grafer, har använt guiden på http://heim.ifi.uio.no/~hpl/Pmw.Blt/doc/. I programmet har jag några textfält (Pmw.EntryField) som användaren ska kunna fylla i värden i, och en graf (Pmw.Blt.Graph). Allt funkar förutom att när man ändrar värdena i textfälten så ändras inte grafen! I ett exempel i ovanstående guide använde de en funktion kallad update_idletasks(), men jag begriper inte riktigt vad det är den gör, och hittar inte nån vettig beskrivning av den med google heller! Jag läser ju in värdena med textfält.getvalue(), textfälten har defaultvärden satta med Pmw.EntryField(value="") och i slutet av programmet anropar jag fönster.mainloop(). Vad (mer) behöver man tänka på för att få programmet att läsa in inskrivna värden?

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 08 okt 2008, 18:57
av gasol
GUI programmering är vad man brukar kalla för "event-driven", dvs att när användaren gör något med programmet, typ skriver en ett tal i ett textfält så är det en händelse, eller "event". Programmet reagerar då på denna händelse. Hur detta sker i olika tool kits är olika.

Men nästan alltid så används något sorts callback-system. Du säger till din GUI toolkit att när användaren trycker på denna knapp, kör denna metod. När användaren har skrivit in något här så kör denna metod. Sedan startar du main-loopen och programmet väntar på att användaren ska göra något intressant...

Olika tool kits kallar dessa callbacks för olika saker, GTK kallar dom för signals, i Java så kallas dom för listeners (om jag inte minns fel) osv, vad Pmw kallar dom har jag ingen aning om, men är nästan säker på att dom använder samma system...

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 10 okt 2008, 15:01
av ai
Hmm...jag har fått det att funka genom att lägga ändringen av grafen i en funktion, som anropas då man trycker på en knapp, såhär:

Kod: Markera allt

Button(win, text = "Update Graph", command = draw_graph)
Funktionen draw_graph är definierad överst i min .py-fil. Brukar man inte då man anropar en funktion använda parenteser, alltså draw_graph() istället för bara draw_graph som ovan? Om jag lägger till dessa parenteser så verkar det som om funktionen körs direkt då programmet startas istället för först då användaren trycker på knappen!! Finns det en logisk förklaring till detta?

Sen så verkar det inte som om saker och ting funkar som vanligt inne i funktionen...kan jag använda variabler som jag skapat tidigare i programmet på samma sätt i funktionen eller måste jag ge en mer fullständig "sökväg"?

Tack så mycket för hjälpen, jag är som ni säkert märker rejäl nybörjare på detta men tycker det går ganska bra ändå! Programmet ifråga ska bli mitt examensarbete i fysikalisk kemi.

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 10 okt 2008, 18:02
av gasol
Button(win, text = "Update Graph", command = draw_graph)

Här är draw_graph vad man brukar kalla för en funktions pekare (iaf i C) Du vill ju inte ropa på funktionen draw_graph när du skapar knappen, utan du vill att knappen ska ropa på funktionen draw_graph _när_ någon klickar på knappen. Därför måste du säga åt knappen att den ska ropa på en viss funktionen när man trycker på den. Det är just det command argumentet är, den funktion som ska ropas på när man trycker på knappen.

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 13 okt 2008, 11:11
av ai
Hmm..jag tror jag vet vad en pekare är: programmet hoppar till en annan minnesadress, och tillbaka igen på kommandot return, right? Vad som nu gör mej lite konfunderad är att mitt program beter sig helt olika beroende på om jag skriver "command=draw_graph" eller "command=draw_graph()", alltså med eller utan parenteser. Utan parenteser verkar det funka som det ska, dvs. funktionen exekveras då användaren trycker på knappen, men om jag inkluderar parenteserna så verkar det som om funktionen exekveras direkt då programmet startas (och inte när man trycker på knappen)! Min fråga till er python-kunniga är alltså: vad är skillnaden på att skriva "draw_graph" och "draw_graph()"? Utan parenteser blir det ju svårt att skicka med några argument till funktionen... ???

En sak till, finns det nått enkelt och smart sätt att se vad programmet gör rad för rad, jag har lekt lite med assembler på AVR-mikrodatorer (inget jag KAN men jag vet hur det funkar litegrann) och där fanns det ju ett väldigt trevligt program där man kunde se precis vad som hände med variabler och så instruktion för instruktion, finns det något som ens vagt liknar detta för python? Det e väldigt svårt att veta vart nånstans det går åt skogen när man e tvungen att köra hela programmet på en gång och sen gissa!

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 13 okt 2008, 13:31
av micke_nordin
ai skrev: En sak till, finns det nått enkelt och smart sätt att se vad programmet gör rad för rad, jag har lekt lite med assembler på AVR-mikrodatorer (inget jag KAN men jag vet hur det funkar litegrann) och där fanns det ju ett väldigt trevligt program där man kunde se precis vad som hände med variabler och så instruktion för instruktion, finns det något som ens vagt liknar detta för python? Det e väldigt svårt att veta vart nånstans det går åt skogen när man e tvungen att köra hela programmet på en gång och sen gissa!
Jag vet inte om det finns någon Python-debugger (nån annan vet säkert), något väldigt enkelt man kan göra är ju att lägga in utskrifter i funktionerna och huvudprogrammet som berättar var man är. Om jag inte har tillgång till en debugger av nån anledning (typ inte vet vad jag skall använda för det programspråket eller nått) så skriver jag utskrifter i huvudprogrammet före varje anrop av en funktion, då kan jag ser var programmet krashar. När jag vet vilken funktion som har problem, lägger jag i stället in utskrifterna i den funktionen på olika ställen ochj på så sätt kan man få reda på var det går fel.

Enkelt, men effektiv.

/Micke

Re: Enkelt GUI: rita grafer, hur uppdatera?

Postat: 13 okt 2008, 17:40
av gasol
gasol skrev:Button(win, text = "Update Graph", command = draw_graph)

Här är draw_graph vad man brukar kalla för en funktions pekare (iaf i C) Du vill ju inte ropa på funktionen draw_graph när du skapar knappen, utan du vill att knappen ska ropa på funktionen draw_graph _när_ någon klickar på knappen. Därför måste du säga åt knappen att den ska ropa på en viss funktionen när man trycker på den. Det är just det command argumentet är, den funktion som ska ropas på när man trycker på knappen.

Skillnaden mellan draw_graph och draw_graph() är att när du har med parenteserna så anropar du funktionen. Om du inte har med parenteserna så skickar du en referens till funktionen, som programmet sedan kan anropa.

Här är ett litet exempel, jag kanske var otydlig i min förra post

Kod: Markera allt

>>> a = "test"
>>> f = a.__len__ # __len__ är en metod som ger dig längden på strängen.
# f är här en referens till a.__len__ 
>>> f
<method-wrapper '__len__' of str object at 0xb7db2cc0>
>>> f() # Här anropar jag metoden som f pekar på, dvs a.__len__() vilket ger mig svaret 4
4
>>> a.__len__()
4
>>> a.__len__
<method-wrapper '__len__' of str object at  0xb7db2cc0>
En sak som man bör göra skillnad på är, funktioner och metoder. Dom är i princip samma sak. Men en metod definieras i en klass, och är associerad med ett objekt.

Kod: Markera allt

>>> a = "test-test" # a är nu en ny sträng.
>>> f () # f är fortfarande en referens till a.__len__ på den gamla strängen. Därför är längden 4!
4 
>>> a.__len__
<method-wrapper '__len__' of str object at 0xb7922ef8>
>>> f = a.__len__
>>> f()
9
Om jag använder parenteserna så anropar jag funktionen.

Kod: Markera allt

>>> f = a.__len__() # Om jag hade skrivit detta istället så hade f blivit tilldelat värdet 9
>>> f
9