Dagens föreläsningar

Relevanta dokument
Grafiska användargränssnitt

TDB/IT, Uppsala universitet 1

Idag: Centrerad utskrift. Granskning. DD1311 Programmeringsteknik med PBL. Granskning Felhantering GUI. Föreläsning 15.

Skolan för Datavetenskap och kommunikation. Programmeringsteknik. Föreläsning 16

Skolan för Datavetenskap och kommunikation PROGRAMMERINGSTEKNIK FÖRELÄSNING 15

Mer till P-uppgiften: Dokumentation. Nyheter. Algoritm för sökning. Mer hjälp. DD1311 Programmeringsteknik med PBL

Grafiska användargränssnitt i Java

Grafiska användargränssnitt i Java

Objektorienterad programmering Föreläsning 15. Grafiska användargränssnitt (GUI Graphical User Interface)

Starta ett fönster... Hur håller tkinter reda på musklick? Olika sätt att organisera fönsterinnehåll. Och för att placera våra widgets

Objektorienterad programmering Föreläsning 2

Kort om klasser och objekt En introduktion till GUI-programmering i Java

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Python. Python är, som Scheme, ett interpreterat språk men det finns kompilatorer för Python.

Laboration: Whitebox- och blackboxtesting

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

EnKlass. Instans 3 av EnKlass. Instans 2 av EnKlass

Klasshierarkier - repetition

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Grafiska användargränssnitt i Java

729G75: Programmering och algoritmiskt tänkande. Tema 1. Föreläsning 1 Jody Foo

Sätt att skriva ut binärträd

Syfte : Lära sig objektorienterad programmering Syfte : Lära sig programmering i ett OO-språk vilket?

Objektorienterad Programkonstruktion. Föreläsning 3 9 nov 2015

Objektorienterad Programkonstruktion. Föreläsning 3 7 nov 2016

TDP002 Imperativ programmering

Mer grafik. Jan Erik Moström

Föreläsning 16 Arv. Jan Lönnberg T Grundkurs i programmering

DI-institutionen Sid 1 av 6 Hans-Edy Mårtensson Sten Sundin

Objektorienterad programmering

JavaScript. Innehåll. Historia. Document object model DHTML. Varför Javascript?

PROGRAMMERINGSTEKNIK TIN212

Imperativ programmering. Föreläsning 4

ITK:P1 Föreläsning 4. Grafiska gränssnitt i Java. AWT-komponenter

Labb i Datorsystemteknik och programvaruteknik Programmering av kalkylator i Visual Basic

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 11 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Ordlistor, filhantering och ut på webben. Linda Mannila

TDDD78, TDDE30, 729A Introduktion till Java -- för Pythonprogrammerare

Windows Forms Winstrand Development

Kopiering av objekt i Java

Java: Utvecklingsverktyg, datatyper, kontrollstrukturer

Bankkonto - övning. Övning 2 Skriv en metod, geträntan, som returnerar räntan.

Objektorienterad programmering med Java Swing: Händelser, lyssnare och applets

Komponenter med COM (och COM+/VC++ 7.0)

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Classes och Interfaces, Objects och References, Initialization

(Man brukar säga att) Java är... Denna föreläsning. Kompilering av Java. Historik: Java. enkelt. baserat på C/C++ Allmänt om Java

Interface. Interface. Tobias Wrigstad (baserat på bilder från Tom Smedsaas) 3 december 2010

Objektorienterad programmering, allmänt

Viktiga egenskaper hos ett program (Meyer): Objektorienterad programmering, allmänt. Vilka egenskaper vill vi att våra program ska ha?

Hos vad? och bör därför vara instanseller klassvariabel i vilken klass?

Kursplanering Objektorienterad programmering

Inledande programmering med C# (1DV402) Ditt första C#-program med Visual Studio

TDP002 - Imperativ programmering

PROV. 12 Egenskaper (provavsnitt)

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

v. 42 Python HT17 En introduktion Oscar Bergqvist

Laboration 1 Introduktion till Visual Basic 6.0

TDP002 - Imperativ programmering

"Är en"-relation. "Har en"-relation. Arv. Seminarium 2 Relevanta uppgifter. I exemplet Boll från förra föreläsningen gällde

Programmering B med Visual C

Introduktion till programmering. Programspråk och paradigmer

TDDD78, TDDE30, 729A Introduktion till Java -- för Pythonprogrammerare

729G75: Programmering och algoritmiskt tänkande. Tema 1, föreläsning 1 Jody Foo

2I1049 Föreläsning 5. Objektorientering. Objektorientering. Klasserna ordnas i en hierarki som motsvarar deras inbördes ordning

ITK:P1 Föreläsning 1. Programmering. Programmeringsspråket Java. Stark typning Explicit typning Strukturerat Hög säkerhet

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Objektorienterade programmeringsspråk. Objektorienterade språk. Den objekt-orienterade modellen. Jämför med icke-oo

Inledande programmering med C# (1DV402) Introduktion till C#

729G04 Programmering och diskret matematik. Föreläsning 7

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Objektorienterad programmering. Grundläggande begrepp

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Högskolan Dalarna sid 1 av 7 DI-institutionen Hans-Edy Mårtensson Sten Sundin

Föreläsning 15: Repetition DVGA02

729G06 Programmering och logik. Info om pythondelen & introduktion till objektorienterad programmering.

Introduktion till programmering SMD180. Föreläsning 9: Tupler

DAT043 - Föreläsning 7

Programmering grundkurs

Introduktion till programmering SMD180. Föreläsning 2: Variabler, uttryck och satser

Språket Python - Del 1 Grundkurs i programmering med Python

Objektorienterad Programmering (TDDC77)

Command line argumenter. Objektorienterad Programmering (TDDC77) Vad blir resultatet? Nu då? Ahmed Rezine. Hösttermin 2016

F6 Objektorienterad design. ID1004 Objektorienterad programmering Fredrik Kilander

725G61 - Laboration 7 Implementation av ett API. Johan Falkenjack

Chapter 4: Writing Classes/ Att skriva egna klasser.

DD2385 Programutvecklingsteknik Några bilder till föreläsning 1 24/ Kursöversikt Javarepetition/Javaintroduktion

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Föreläsnings 11 - GUI, Händelsestyrda program, MVC

Universitetet i Linköping Institutionen för datavetenskap Anders Haraldsson

Exempel: Exempel: Exempel: Exempel: $djur=array("ko","katt","älg"); foreach ($djur as $d) { echo $d. " "; } Resultat. ko katt älg

Överlagring, static, testning, formella metoder och undantag! Förelasning 13!! TDA540 Objektorienterad Programmering!

Använda Python Laboration 1 GruDat, DD1344

Grundläggande datalogi - Övning 1

Läsöversikt. Föreläsningar 2-6. Genomförande av laborationer

Föreläsning 8 Programmeringsteknik och Matlab DD1312. Klassmetod. Egen modul

Transkript:

Dagens föreläsningar Iteratorer Utvecklingsmönster och PyUnit Grafik och grafiska användargränssnitt (GUI) Orientering andra dynamiska språk Liten presentation av Ruby

Iteratorer

Iteratorer En av de vanligaste uppgifterna i ett program är att repetera kod. I många språk genomförs dessa loopar med hjälp av numeriska index. En annan lösning är att använda iteratorer. För att slippa loopar som tex: for i in range(len(a)) Designfilosofi: Låt varje objekt vara ansvarigt för sitt innehåll. En iterator säger "Jag kan gå igenom hela min datamängd ett objekt i taget". En användare av en iterator säger "Jag vill utföra något för alla objekt i den här samlingen".

Exempel med beräkningsdomän Anta att Mesh är en klass som definierar en tvådimensionell beräkningsdomän bestående av ett rutnät med värden i noder. Följande kodfragment skapar ett nät för nuvarande värden och ett för ändringen. Därefter uppdateras randen och innandömet med lämpliga FDM-stenciler. currentmesh = Mesh() changes = calculatechanges(currentmesh) # Returnerar ett Mesh-objekt for x in range(len(currentmesh.nx)): for y in range(len(currentmesh.ny)): if x > 0 and x < currentmesh.nx 1 and \ y > 0 and y > currentmesh.ny - 1: currentmesh[x][y] += changes[x][y] else: currentmesh[x][y] = BC(x,y)

Dags för uppdatering Anta nu att klassen Mesh utökas med en eller flera av följande förändringar: Stöd för N dimensioner. Diskretiseringen byts till triangelformade finita element. Parallellisering införs där nätet delas upp mellan olika processorer. Ett glest matrisformat används för lagring av värdena och värden mindre än ett tröskelvärde betraktas som 0. Möjlighet att ha ränder inuti domänen, eller flera icke sammanhängande domäner.

Konsekvenser Samtliga dessa förändringar resulterar i att vår existerande kod kanske inte fungerar som väntat. Betrakta nu följande kod: currentmesh = Mesh() for coord in currentmesh.innerpoints(): currentmesh.calcchange(coord) for coord in currentmesh.boundary(): currentmesh.calcboundarychange(coord) Här förutsätts ingenting om Mesh:s interna datastruktur. Därmed kan uppdateringarna göras oberoende av intern struktur. Kanske är for-loopen helt onödig? currentmesh = Mesh() currentmesh.calcchange()

En variant av range class my_range: def init (self,last=10): self.last=last; def iter (self): self.current_number = -1 return self def next(self): self.current_number += 1 if self.current_number == self.last: raise StopIteration return self.current_number $ python my_range.py 0 1 2 3 4 5 6 7 8 9 if name == " main ": for n in my_range(10): print n

En användbar iterator # -*- coding: utf-8 -*- # iterator_01.py class ColorIterator: colors = ["Red", "Green", "Blue", "Yellow", "Black", "Brown"] def iter (self): self.current_color = -1 return self $> python iterator_01.py Red Green Blue Yellow Black Brown def next(self): self.current_color += 1 if self.current_color == len(self. class.colors): raise StopIteration return self. class.colors[self.current_color] if name == " main ": ci = ColorIterator() for color in ci: print color

Implementera med yield Satsen yield lagrar en funktions tillstånd. Nästa gång funktionen anropas kommer exekveringen att fortsätta efter yield-satsen, med lokala variabler intakta. Inte hela sanningen! Se help( yield ). # -*- coding: utf-8 -*- # iterator_02.py def colors(available = ["Red", "Green", "Blue", "Yellow", "Black", "Brown"]): for color in available: yield color $> python iterator_02.py Red Green Blue Yellow Black Brown if name == " main ": for color in colors(): print color

Fibonacciserie med iterator Fibonacciserien är en talserie som inleds med 0 och 1. Därefter är varje tal summan av föregående två tal, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144 Serien dyker upp på många ställen inom exempelvis biologin. Serien är oändlig och passar därför bra för att implementeras som en iterator. Varför inte rekursivt i Python? # -*- coding: utf-8 -*- # iterator_03.py def fib(limit=10): x, y, count = 0, 1, 0 while count < limit: yield x x, y = y, x + y count += 1 if name == " main ": for num in fib(15): print num,

Skapa en lista från en operator menten i en iterator kan vi använda # -*- funktioner coding: utf-8 från -*- modulen iterto # iterator_04.py def fib( ): x, y = 0, 1 while True: yield x x, y = y, x + y if name == " main ": import itertools print list(itertools.islice(fib(), 10)) $> python iterator_04.py [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Parallella iteratorer # -*- coding: utf-8 -*- gar parallellt används funktionen izip, också från itertools. # iterator_05.py import itertools era funktioner för iteratorer, se dokumentationen för detaljer. a = ["a1", "a2", "a3", "a4"] b = ["b1", "b2", "b3"] if name == " main ": for x, y in itertools.izip(a, b): print x, y $> python iterator_05.py a1 b1 a2 b2 a3 b3

http://www.secnetix.de/olli/python/lambda_functions.haw k Filter och lambda Filter används för att ta bort element ur sekvenser. kort_sekvens=filter(funktion, sekvens) Lambda används för att skriva (anonyma) funktioner >>> g = lambda x: x*x >>> g(3) 9 >>> >>> nums = range(2, 50) >>> for i in range(2, 8):... nums = filter(lambda x: x == i or x % i, nums)... >>> print nums # ger vad?

Testdriven programutveckling

Testa kod För små program är det ofta enkelt att avgöra om det gör vad det ska. Ju mer komplext och omfattande ett program blir desto svårare blir det att överblicka. Ändringar i en del av koden får inte resultera i att existerande funktionalitet fallerar. Detta kräver någon form av systematisk testning av kod.

Unit testing Unit testing innebär att man isolerar olika beteenden hos ett objekt och verifierar att dessa fungerar som förväntat. Exempelvis kan man kontrollera att en kod som ska hantera lösenords giltighet godkänner respektive underkänner givna exempellösenord. Ofta kopplas ett test till varje objekt i en applikation. Ett bra unit test testar så stor del som möjligt av objektet samtidigt som varje deltest är så oberoende som möjligt. Genom att ha oberoende test minskar man den kod som behöver felsökas då ett fel uppstår.

Test Driven Development Test Driven Developmen, TDD, är en metod för att skapa testkod till applikationer. Då man använder TDD låter man unit testing vara en styrande del i utvecklingsprocessen. Enheter defineras av tester som skrivs innan enheten själv. Därmed kommer den färdiga applikaitonen ha en testsvit som kontrollerar att varje liten del fungerar som den ska. Det finns även andra former av testning.

TDD:s fem steg Lägg till ett test. Kontrollera att testet fallerar. Gör en minimal implementation för att klara testet. Kontrollera att hela testsviten klaras. Refaktorisera koden.

Exempel TDD Anta att vi har en klass som hanterar taxibilar. Vi har instansvariabler som hanterar körd sträcka och aktuell taxa. Förutsättningen är att programmet klarar alla test i nuvarande testsvit vid varje TDD-rundas början.

Existerande kod # -*- coding: utf-8 -*- # taxi.py Vi vill nu lägga till en metod som returnerar class Taxi: total kostnad för aktuell def init (self, fare, distance): resa. self.fare = fare self.distance = distance $> python taxi_test.py. ------------------------------------ Ran 1 test in 0.000s # -*- coding: utf-8 -*- # taxi_test.rb import unittest from taxi import Taxi class TaxiTestCase(unittest.TestCase): def setup(self): self.taxi = Taxi(12, 87) def teardown(self): pass def testcreation(self): assert self.taxi.fare == 12 assert self.taxi.distance == 87 def suite(): suite = unittest.testsuite() suite.addtest(taxitestcase("testcreation")) return suite if name == " main ": unittest.main()

Steg 1: Lägg till ett test Ett test kan läggas till som en ny assertion i ett existerande test eller som ett nytt testfall. Vi väljer att lägga till ett nytt testfall. Vi utformar vårt test så att den färdiga koden ska klara det, väl medvetna om att existerande kod inte har denna funktionalitet än. # -*- coding: utf-8 -*- # taxi_test.rb import unittest from taxi import Taxi class TaxiTestCase(unittest.TestCase): def setup(self): self.taxi = Taxi(12, 87) def teardown(self): pass def testcreation(self): assert self.taxi.fare == 12 assert self.taxi.distance == 87 def testtotalprice(self): assert self.taxi.total_cost() == 12*87 def suite(): suite = unittest.testsuite() suite.addtest(taxitestcase("testcreation")) suite.addtest(taxitestcase("testtotalprice")) return suite if name == " main ": unittest.main()

Steg 2: Kontrollera att testet fallerar För att kunna kontrollera att testet misslyckas "på rätt sätt" måste vi lägga till en tom metod. $> python taxi_test.py.f ==================================== FAIL: testtotalprice ( main.taxitestcase) ------------------------------------ Traceback (most recent call last): File "taxi_test.py", line 20, in testtotalprice assert self.taxi.total_cost() == 12*87 AssertionError ------------------------------------ Ran 2 tests in 0.000s FAILED (failures=1) # -*- coding: utf-8 -*- # taxi.py class Taxi: def init (self, fare, distance): self.fare = fare self.distance = distance def total_cost(self): return 0

Steg 3 och 4: Minimal implementation och klarat test Här görs en så liten implementation som möjligt som klarar testet. Därefter kontrolleras om testsviten klaras. Om inte så görs förändringar i koden till sviten klaras. Om fel uppstår i programdelar som inte berörs av det aktuella testet indikerar detta oönskade kopplingar i koden. # -*- coding: utf-8 -*- # taxi.py class Taxi: def init (self, fare, distance): self.fare = fare self.distance = distance def total_cost(self): return self.fare * self.distance $> python taxi_test.py.. ----------------------------------------- Ran 2 tests in 0.000s OK Båda testen klaras

Steg 5: Refaktorisering Refaktorisering innebär att ett objekt ändras internt utan att dess externa gränssnitt påverkas. I detta fall behövs inga ändringar men för större koder kan "uppstädning" behövas. Genom att köra testsviten kan vi garantera att refaktoriseringen fortfarande har samma funktion som tidigare. Refaktorisering kan introducera buggar som inte täcks av testsviten.

Korta kommentarer Undvik för omfattande test. Kan tyda på "gudsobjekt". TDD är en konst som kräver träning! Man tvingas bli konsument av sin egen kod. Även TDD-genererad kod innehåller buggar, men samma bugg behöver bara hanteras en gång.

Grafiska användargränssnitt

Grafiska användargränssnitt Varför finns grafiska användargränssnitt? Hur är de uppbyggda? Skapa grafik i Python. Ett antal exempel. Händelsehantering. Tips inför projekten.

Varför använda grafik (GUI)? Öka användbarheten. Minska inlärningströskeln. Inte alltid bästa lösningen, exempelvis kan terminalgränssnitt vara lämpligt för systemadministration. Kan vara bra att erbjuda flera olika gränssnitt. Sist men abslout inte minst: Psykologisk effekt.

Grafikbiblioteket Tkinter De facto standard, följer med (nästan) alla standardinstallationer. Står för Tk interface och kan ses som ett kopplingsbibliotek mellan Tk GUI toolkit och Python. (dvs en adapter eller wrapper) Ett av flera sätt att skapa grafik i Python.

Plattformsoberoende grafik Python finns för en mängd plattformar, exempelvis Unix, Linux, Windows och Mac OS X. Utseendet måste följa plattformarnas standarder utan att kräva ändringar i koden. Kräver en abstrakt beskrivning av ingående widgets, snarare än exakta grafikdetaljer. Fördel: Portabel kod även för grafik. Nackdel: Svårt att skapa exakta gränssnitt. De flesta GUI-moduler är sk abstract factories

Hur är ett GUI uppbyggt?

Ett första kodexempel # first_example.py from Tkinter import * root = Tk() my_widget = Label(root, text="hello world") my_widget.pack() root.mainloop()

Genomgång av programmet # first_example.py from Tkinter import * root = Tk() my_widget = Label(root, text="hello world") my_widget.pack() root.mainloop() Programmet följer en arbetsordning för att skapa widgets: apa en huvudbehållare, i detta fall ett Tk-objekt. apa en widget av den typ man vill ha, här ett Label-objekt. ge egenskaper för widgeten, tex. färg och form. nropa pack-metoden för att lägga till widgeten i gränssnittet. petera steg 2-4 för varje widget. ropa mainloop-metoden för huvudbehållaren för att visa den och alla underliggande widg

Packa widgets Packaren anropas för varje widget med önskemål om hur widgeten ska se ut och bete sig. Önskemålen innefattar dels ursprunglig placering och utsträckning i en behållare, dels hur widgeten ska förändras då behållaren ändrar storlek. Packaren försöker tillgodose alla önskemål. Om två önskemål krockar tar packaren hänsyn till packordningen, dvs. i vilken ordning pack anropats.

Placering En widgets placering styrs av argument till pack-metoden. Sida i behållaren anges med side och placering längs sidorna med anchor. Widgetens beteende vid förändringar i huvudbehållaren anges med expand och fill.

Exempel på placeringar (PiP 12.2) # graphics02.py from Tkinter import * Button(text="En knapp").pack() mainloop() # graphics03.py from Tkinter import * Button(text="En knapp").pack(anchor=ne) mainloop() phics04.py Tkinter import * n(text="en knapp").pack(expand=yes, oop() fill=both)

Flera widgets # graphics07.py from Tkinter import * Button(text="Knapp 1").pack(side=TOP, fill=x) Button(text="Knapp 2").pack(side=RIGHT, fill=y) Button(text="Knapp 3").pack(expand=YES, fill=both) mainloop()

Flera widgets # graphics08.py from Tkinter import * Button(text="Knapp 2").pack(side=RIGHT, fill=y) Button(text="Knapp 1").pack(side=TOP, fill=x) Button(text="Knapp 3").pack(expand=YES, fill=both) mainloop()

Vanliga widgets Label. Textetikett. (13.1) Button. Klickbar knapp. (13.2) Radiobutton. Välj ett alternativ av flera. (13.3) Checkbutton. Välj valfritt antal alternativ. (13.4) Entry. Läs in kortare text. (13.5) Frame. Ordna grupper av widgets. (13.6)

Mer avancerade widgets Menu. Vanliga menyer. (14.1) Menubutton. Knappar som öppnar en meny. (14.2) Canvas. Målarduk för sammansatt grafik. (14.3) Text. Textruta för längre texter. (14.4) Dialogrutor (egentligen inga widgets). (14.7)

Klasser och arv i Tkinter Varje widgettyp i Tkinter är en klass. Varje widget i ett GUI är ett objekt. Huvudprogrammet kan skapas som subklasser till Tkinter-klasser, exempelvis Tk eller Toplevel. Grafikkomponenter skapas med fördel som subklasser till Tkinter, exempelvis Frame.

En förbättrad textruta # entry01.py from Tkinter import * class ExtendedEntry(Entry): # Konstruktor def init (self, root, **options): # Anropa superklassens konstruktor Entry. init (self, root, options) # Koppla fokus till händelsehanterare self.bind('<focusin>', self.selectall) def selectall(self,event): # Markera all text och sätt markören sist self.select_range(0,end) self.icursor(end) root = Tk() currtext = StringVar() # Kontrollvariabel för texten currtext.set('klicka här för att ändra texten.') ExtendedEntry(root, textvariable=currtext, width=30).pack() root.mainloop()

En återanvändbar komponent # ControlPanel.py from Tkinter import * class ControlPanel(Frame): def init (self, root, **options): # Anropa superklassens konstruktor Frame. init (self, root, options) # Etikett för titelboxen Label(self, text='aktuellt spår:').pack(side=top, fill=x) # Skapa textbox för titel currtracktitle = StringVar() # Kontrollvariabel för texten currtrack = Entry(self, textvariable=currtracktitle).\ pack(side=top, fill=x) # Skapa och packa knappar btnplay = Button(self, text='play') btnplay.pack(side=left, expand=yes, fill=x) btnrewind = Button(self, text='rewind') btnrewind.pack(side=left, expand=yes, fill=x) btnforward = Button(self, text='forward') btnforward.pack(side=left, expand=yes, fill=x) btnstop = Button(self, text='stop') btnstop.pack(side=left, expand=yes, fill=x)

..fortsättning av koden if name == ' main ': # Testa ControlPanel-klassen root = Tk() cp = ControlPanel(root) # Packa hela ramen cp.pack(fill=x) # Starta väntfas root.mainloop() För en applikation som använder denna komponent, se Programmering i Python 20.5.1

Rullbara listor # listbox01.py from Tkinter import * class ScrollListbox(Frame): def init (self, options, parent=none): Frame. init (self, parent) self.pack(expand=yes, fill=both) sb = Scrollbar(self) # Skapa rullisten lb = Listbox(self, relief=sunken) # Skapa listboxen sb.config(command=lb.yview) # Korslänkning lb.config(yscrollcommand=sb.set) # - " - sb.pack(side=right, fill=y) lb.pack(side=left, expand=yes, fill=both) for option in options: # Lägg till valen lb.insert(end, option) # END är listboxens slut lb.bind('<double-1>', self.process) # Kopplar dubbelklick self.listbox = lb def process(self, event): print 'Du valde', self.listbox.get(active) options = [] for i in range(1,21): options.append('val ' + str(i)) # Lägg till val root = Tk() Label(text='Dubbelklicka på ditt val.').pack() ScrollListbox(options).pack() root.mainloop()

Standardisera widgets Det kan vara smidigt att ändra standardutseendet på widgets. # options.txt *background: LightGreen *Button.background: Red # standardvalues.py from Tkinter import * root = Tk() root.option_readfile ('options.txt') Label(root, text='detta är en etikett').pack(side=left) Button(root, text='detta är en knapp').pack(side=left) root.mainloop()

Bilder och bildhantering Bildhantering finns implementerat i Python Imaging Library, PIL. Detta är fritt nedladdningsbart. Hanterar de flesta vanliga (och ett antal ovanliga) bildformat, såsom JPEG, TIFF och PNG. Lägger till text och annan grafik i bilderna. Se PiP 12.7 för detaljer. http://www.pythonware.com/products/pil /

Menyer (PiP 14.1) #menu01.py from Tkinter import * def notimplemented(): print 'Menyvalet är inte implementerat ännu.' def printmenuopened(): print "Du öppnade en meny." root = Tk() # Skapa meny med root som parent topmenu = Menu(root) # Skapa en undermeny med topmenu som parent file = Menu(topMenu, tearoff=0) file.add_command(label='ny', command=notimplemented, underline=0) file.add_command(label='öppna', command=notimplemented, underline=0) file.add_command(label='spara', command=notimplemented, underline=0) file.add_separator() file.add_command(label='avsluta', command=sys.exit, underline=0) # En undermeny till tools = Menu(topMenu,postcommand=printMenuOpened) tools.add_command(label='kompilera', command=notimplemented, underline=0) tools.add_command(label='jämför', command=notimplemented, underline=0)...

fortsättning på menykod. # Skapa en undermeny till sökalternativet searchmenu = Menu(tools, tearoff=0) searchmenu.add_command(label='källkod', command = notimplemented, underline=0) searchmenu.add_command(label='kommando', command = notimplemented, underline=0) searchmenu.add_command(label='dokumentation', command = notimplemented, underline=0) # Skapa menypost med undermeny tools.add_cascade(label='sök', menu=searchmenu, underline=0) # Skapa tvvägslänk mellan root och topmenu root.config(menu=topmenu) # Skapa tvåvägslänkar mellan topmenu och undermenyerna topmenu.add_cascade(label='fil', menu=file) topmenu.add_cascade(label='verktyg', menu=tools) # Innehåll i fönstret Label(root, height=10, width=50, text='välj något i menyerna.').pack() root.mainloop()

Arv inte alltid rätt lösning Att skapa program som subklasser till Tkinterklasser är inte alltid en bra lösning. I en objektorienterad design vill man helst separera logik och presentation (Model-View- Controller, MVC). Anta att vi har kod som hanterar bankkonton och kunder. Om vi skapar logiken som en separat modul kan denna kopplas till ett lokalt GUI, ett webbaserat GUI eller användas från terminalen. Att använda arv eller inte är ett designval. Båda alternativen har för- och nackdelar.

Händelsehantering Ett GUI är ointressant i sig, det måste kunna ta emot inmatning från användaren och agera utifrån denna. Inmatning kan ske via musen, tangentbordet eller annan liknande utrustning. Fokuseringen på händelser förändrar programstrukturen och designen. Passar bra för modularisering och objektorienterad programmering.

Linjärt eller händelsestyrt program I ett linjärt program: Utförs saker i en förutbestämd ordning. Sker all inmatning vid bestämda tillfällen. I ett händelsestyrt program: Finns ofta en central väntslinga (mainloop). Utförs programavsnitt, händelsehanterare, beroende på vilken händelse som sker. Observera att händelsestyrda program inte nödvändigtvis måste vara baserade på ett GUI.

En första händelsehanterare # events01.py from Tkinter import * def onleftclick(event): print event. class label.configure(text="du klickade vänster musknapp.") def onrightclick(event): label.configure(text="du klickade höger musknapp.") root = Tk() label = Label(root, text="") # Skapa etikett label.pack(fill=x) button = Button(root, text="klicka med valfri musknapp") button.bind('<button-1>', onleftclick) # Koppla vänsterklick button.bind('<button-3>', onrightclick) # Koppla högerklick button.pack(fill=x) root.mainloop()

Om händelsehanteraren Kan vara en funktion eller metod. Tar ett argument, ett Event-objekt som innehåller information om händelsen som ägt rum och den widget som genererade den. Samma händelsehanterare kan hantera händelser från flera olika widgets. När händelsehanteraren avslutas återgår programmet till väntfasen igen.

Att definiera en händelse En händelse beskrivs av en sekvens identifierare tillsammans med en eller flera modifierare. Identifierare är exempelvis Button-n, Activate, FocusIn, FocusOut. Se PiP 15.3 för en utförlig lista. Modifierare är exempelvis Alt, Control och Shift, se PiP 15.3.1 <Control-ButtonRelease-1> anger att vänstra musknappen tryckts in och släppts samtidigt som control-tangenten hållts in.

Fler vanliga händelser Activate/Deactivate. Widgeten ändrar stateattributet. Configure. Widgeten ändrar storlek. Double-n. Musknapp n har dubbelklickats. KeyPress-key. Tangenten key har tryckts in. KeyRelease-key. Tangenten key har släppts. Enter. Muspekaren förs in över widgetens synliga delar. Leave. Muspekaren lämnar widgetens synliga delar.

Event-objektet # events05.py from Tkinter import * def onmouseclick(event): print 'Du klickade med knapp', event.num root = Tk() button = Button(text="Klicka på mig") button.bind('<any-button>', onmouseclick) button.pack(fill=x) root.mainloop() Andra användbara attribut för Event-objektet är: time, serial, widget, x och y. Se PiP 15.6 för en utförligare lista.

Ändra egenskaper dynamiskt Hittills har alla widgets egenskaper angetts då widgeten skapas. Naturligtvis går det även att ändra dessa dynamiskt under programmets gång. Egenskaperna sätts med metoden configure eller config. Egenskaper avläses med metoden cget. Egenskaper kan också sättas och avläsas med hakparenteser liknande ett dictionary: w[ foreground ] = red print w[ foreground ]

Exempel på dynamisk grafik # events06.py from Tkinter import * def togglecolor(): if label.cget("background") == "red": label.config(background="green") else: label.config(background="red") root = Tk() label = Label(root, text="text", background="green") label.pack(expand=yes, fill=both) Button(root, command=togglecolor, text="byt färg").pack(side=bottom,fill=x) root.mainloop()

Kontrollvariabler Används för att smidigt hantera data från widgets. Kan kopplas till flera widgets som därmed hålls synkroniserade. Innehållet kan antingen ändras av användaren via en widget eller av programmet via kontrollvariablen.

Exempel med kontrollvariabler # events07.py from Tkinter import * root = Tk() t = StringVar() # Skapa kontrollvariabel t.set('detta värde ges till båda objekten') # Sätt startvärde # Knappens och textrutans text kopplas till samma variabel Button(root,textvariable=t).pack(fill=X) Entry(root, textvariable=t).pack(fill=x) root.mainloop()

Kryssrutor och kontrollvariabler # checkbutton01.py from Tkinter import * def printform(): if haslicence.get(): print 'Personen har körkort.' if hasowncar.get(): print 'Personen har egen bil.' import sys sys.exit() root = Tk() haslicence = IntVar() Checkbutton(root,text = 'Körkort', variable =haslicence).pack(anchor=w) hasowncar = IntVar() Checkbutton(root,text = 'Egen bil',variable = hasowncar).pack(anchor=w) Button(root,text = 'Spara',command = printform).pack(anchor=s) root.mainloop()

Gruppera radioknappar # radiobutton01.py from Tkinter import * def onmealclick(): print mealvar.get() def ondrinkclick(): print drinkvar.get() root = Tk() mealvar = StringVar() meals = ['Frukost','Lunch','Middag'] for meal in meals: Radiobutton(root,command = onmealclick, text = meal, value = meal, variable = mealvar).pack(anchor=w) drinkvar = StringVar() drinks = ['Mjölk','Vatten','Läsk'] for drink in drinks: Radiobutton(root,command = ondrinkclick, text = drink, value = drink, variable = drinkvar).pack(anchor=w) root.mainloop()

Tidsberoende widgets För att ange att en händelse ska utföras efter en viss tid används metoden after. w.after(time, func, *args) Här kommer funktionen/metoden func att anropas med argumenten *args efter time millisekunder. Kan användas för att tex visa en klocka.

Andra sätt att skapa grafik Python Megawidgets, PMW, tar vid där Tkinter slutar. Microsoft Foundation Classes, endast tillgängligt för Windows. wxpython, snabbt och på frammarsch. Jython, Pythonimplementation i Java, ger tillgång till Javas grafik. GTK+ (GIMP Toolkit). PyGTK. Qt. PyQt. (inte helt gratis) Ncurses (nästa slide) http://wiki.python.org/moin/guiprogrammin g

Nästan GUI - ncurses http://www.msncp.com.ar/screenshots.php

Andra dynamiska språk

Andra språk Förutom Python finns många andra dynamiska språk som kan vara lämpliga att känna till. Varje språk har en egen (mer eller mindre väl definierad) nisch och har fördelar och nackdelar. Python har vi redan stiftat bekantskap med. Perl kommer att presenteras torsdag 25:e juni. Ruby kommer få en lite närmare introduktion nedan. Här kommer en kort-kort presentation av andra språk som kan vara av intresse (långt från komplett).

PHP Utvecklades ursprungligen för att generera dynamiska webbplatser. Används nästan uteslutande på webben även om fristående applikationer är möjliga. Stöder OOP såväl som procedurbaserad programmering. Fördelar: Enorm användarbas. Väl anpassat för webben med många bibliotek. Nackdelar: Ej komplett stöd för Unicode. Inga namnrum. Typhanteringen kan ställa till problem.

ECMAScript Standardiserades i ECMA-262-specifikationen. Används ofta synonymt med de två vanligaste implementationerna JavaScript och JScript. Används främst i webbläsare. Fördelar: Möjliggör exekverandet av kod hos klienten utan installation av ny programvara. Nackdelar: Frågetecken kring säkerhet. Olika dialekter (håller på att standardiseras).

Groovy OO-språk designat för Javaplattformen. Lånade delar från Python, Ruby och Smalltalk. Groovy har Javaliknande syntax som kompileras dynamiskt till bytekod. Några skillnader mot standard-java Statisk och dynamisk typning Inbyggt stöd för listor, mappningar, fält och reguljära uttryck.

Lisp En språkfamilj. Skapades ursprungligen av John McCarthy 1958. Används ofta för programmering av artificiell intelligens. Har fått ett uppsving på 2000-talet med open sourcevarianten Common Lisp.

Smalltalk Finns i många varianter, oftast åsyftas Smalltalk-80. Rent objektorienterat språk. Allt sker genom att objekt skickar meddelanden till andra objekt. Smalltalk har inspirerat funktionalitet i många andra språk, exempelvis Ruby.

Ruby Skapades av Yukihiro "Matz" Matsumoto i början an 1990- talet. Språket släpptes officiellt 1995 och har de senaste fem åren vuxit enormt snabbt. Ruby är designat för att ge ökad produktivitet samtidigt som det ska inspirera kreativ och vacker programmering. "Principle of least surprise" I grunden objektorienterat. "Allt är objekt" är inte bara en floskel. Kan även hantera funktionell eller procedurbaserad programmering. Mest likt Perl och Python men har även byggt vidare på många idéer från Smalltalk.

Likheter mellan Python och Ruby Det finns en interaktiv prompt, irb. Det finns en motsvarighet till pydoc, ri. Inga radbrytningstecken behövs. Listor och hashtabeller har samma notation. Har stark, dynamisk typning. Alla variabler är referenser. Felhantering fungerar på samma sätt, men med andra nyckelord. I stort känns Ruby väldigt välbekant för en Pythonprogrammerare och vice versa.

Skillnader mellan Python och Ruby I Ruby är strängar inte statiska. finns äkta konstanter. styrs variablers räckvidd av namnkonventioner. är reguljära uttryck en inbyggd typ. är parenteser valfria i metodanrop. ersätter mixins (liknande interface i Java) multipelt arv. kan klasser öppnas och modifieras under exekvering. används iteratorer mer konsekvent. används block för att skapa flexibel och lättanvänd kod.

Öppna klasser I Ruby är klassdefinitionerna inte stängda. Detta medför att existerande objekt kan ges nya metoder efter det att de skapats. class ExampleClass def talk() print "Hejsan\n" end end e = ExampleClass.new() e.talk class ExampleClass def talk_more() print "Hej igen\n" end end e.talk e.talk_more

Individuellt beteende inom klassen I Ruby kan även enskilda existerande objekt utökas med nya metoder. Detta innebär att objekt inom samma klass inte nödvändigtvis har samma uppsättning metoder. class ExampleClass def talk() print "Hejsan\n" end end e = ExampleClass.new() e.talk def e.talk_more() print "Hej igen\n" end e.talk e.talk_more e2 = ExampleClass.new() e2.talk_more # => Method missing

Inkrementell klassdefinition Vad får detta för konsekvenser för programdesignen i Ruby? Inkrementella klassdefinitioner gör att det blir lättare att strukturera källkoden. Det går inte att identifiera ett objekts metoder genom att enbart studera källkoden Introspektion blir en viktig del av programmet.

Callbacks eller krokar En dynamisk ingrediens i Ruby är möjligheten att hantera callbacks för vissa händelser. Callbacks kan ses som händelsehanterare för händelser som genereras av Rubytolken. Exempel på callbacks är: En metod som inte finns anropas. En klass blir ärvd. En metod läggs till ett objekt.

Exempel på callbacks Klassen Cookbook är en samling med egna data. Genom att implementera method_missing kan alla beteenden som är förknippade med samlingen @recipes skickas vidare. Detta gör att metoder kan anropas direkt för Cookbook-instanser som om de definierats i Cookbook-klassen. class Cookbook attr_accessor :title, :author def initialize @recipes = [] end end def method_missing(m,*args,&block) @recipes.send(m,*args,&block) end