onsdag 27 mars 2013

En målarduk

För att visa olika former av grafik finns objektet Canvas.  Canvas använder ett koordinatsystem med origo i övre vänstra hörnet och en pixel per enhet. Y-axeln är riktad nedåt.

Exempel:

from tkinter import *

root = Tk()

w = Canvas(root, width=200, height=100, bg="white")
w.pack()

w.create_line(0, 0, 200, 100)
w.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))

w.create_rectangle(50, 25, 150, 75, fill="blue")

mainloop()

Metoder för att skapa objekt på en Canvas är:
  • create_line
  • create_rectangle
  • create_arc
  • create_oval
  • create_polygon
  • create_text
  • create_window
  • create_bitmap
  • create_image
Se sida 209-210 i boken samt här.

Som synes ovan kan du även konfigurera utseendet på olika objekt med hjälp av angivelser av färger (bg i koden ovan står för background colour) och andra attribut.

Uppgift 3.2
Rita en smiley med tkinters Canvas

Saker som rör sig och att reagera på musklick

Genom att binda en  händelsehanterare till en Canvas kan du göra olika saker vid musklick eller annat som användaren gör. Bindandet gör med metoden .bind("Namn", funktion).
Namn anger händelsen som ska bindas till funktionen. Se här för lista. Se även boken sid. 238-245
funktion är den funktion som ska köras vid händelsen. Alla händelsefunktioner har argumentet event som är en referens till händelseobjektet som innehåller data om händelsen.

Objekten som ritas på en Canvas kan modifieras och förflyttas efter att de ritats. Detta är möjlig då varje objekt ges ett unikt id-nummer i och med att det skapas. Vid förändringarna hänvisas till dessa id-nummer. Se även boken sid. 213-220

Nedanstående exempel ritar ut en bild med en grön prick. Om användaren klickar på musknappen flyttas pricken 10 pixlar snett nedåt.


from tkinter import *

root = Tk()
root.title('Dot')

def klick_b1(event):
    w.move(dot_id, 10, 10)

w = Canvas(root, width=200, height=200, bg="white")
w.bind("<Button-1>", klick_b1)
photo = PhotoImage(file="../greendot.gif")
dot_id=w.create_image(30, 30, image=photo)
w.pack()
mainloop()

Övning 3.7
Skriv in programmet ovan och testa. Bilden på den gröna pricken laddar du ner och placerar i din projektmapp:

  

Global eller klass

Funktioner kan normalt endast läsa globala variabler, inte ändra dem. Detta är ett problem för händelsebindningar i Python. Du skulle behöva skicka med informationen till funktionen som körs vid händelsen men tyvärr går inte det på ett enkelt sätt då man endast anger funktionens namn. Det finns två olika lösningar på problemet:

global

För att kunna ändra globala variabler i en funktion måste de deklareras först i funktionen med nyckelordet global. Ex:

from tkinter import *

root = Tk()
root.title('Dot')
x=30
y=30
dx=10
dy=10

def klick_b1(event):
    global x, y
    w.move(dot_id, dx, dy)
    x=x+dx
    y=y+dy
    print(str(x)+","+str(y))

w = Canvas(root, width=200, height=200, bg="white")
w.bind("<Button-1>", klick_b1)
photo = PhotoImage(file="../greendot.gif")
dot_id=w.create_image(x, y, image=photo)
w.pack()
mainloop()

Klass
Att använda global passar bra i mindre program men det är bättre att hantera objekt när programmen blir lite större. Genom att skapa en egen underklass till Canvas kan du lägga till de data och funktioner du behöver och hantera dessa. Denna lösning ger ser ut så här:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=200, height=200, bg="white")
        self.bind("<Button-1>", self.klick_b1)
        self.x=30
        self.y=30
        self.dx=10
        self.dy=10
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=self.create_image(self.x, self.y, image=self.photo)
        self.pack()
        
    def klick_b1(self, event):
        self.move(self.dot_id, self.dx, self.dy)
        self.x=self.x+self.dx
        self.y=self.y+self.dy
        print(str(self.x)+","+str(self.y))

root = Tk()
root.title('Dot')
Dot_Canvas(root)
mainloop()

Lösningen med klass är som synes  "klumpigare" för små testprogram men har stora fördelar då programmen blir större. Den nya klassen Dot_Canvas innehåller allt den behöver för sin funktion och kan skapas enkelt i huvudprogrammet.

Använd valfri metod för att lösa nedanstående:

Övning 3.8
Ändra i programmet ovan så att punkten ser ut att studsa när den når sidorna på fönstret.


Uppgift 3.3
Händelseinformationen som finns i objektet event i koden ovan innehåller bland annat information om var muspekaren var när händelsen inträffade. Detta är lagrat som event.x och event.y. Använd exemplet ovan som grund till ett program som placerar den gröna pricken där användaren klickar.

Inga kommentarer:

Skicka en kommentar