måndag 15 april 2013

Rörelse och interaktion

Automatisk rörelse

Tkinter har metoden after( tid, funktion) som anropar en funktion efter tiden tid som anges i millisekunder. Denna kan användas för att skapa rörelse i ett grafisk program.

Övning 3.9
Skriv in och testa programmet nedan:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=30
        self.y=30
        self.dx=5
        self.dy=5
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=self.create_image(self.x, self.y, image=self.photo)
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        self.move(self.dot_id, self.dx, self.dy)
        self.x=self.x+self.dx
        self.y=self.y+self.dy
        if self.x < 10 or self.x > 390 : 
            self.dx=-self.dx
        if self.y < 10 or self.y > 290 : 
            self.dy=-self.dy
        if self.running :
            self.after(50, self.move_dot)

root = Tk()
root.title('Moving dot')
Dot_Canvas(root)
mainloop()

Notera funktionen hos programmet. När användaren klickar på musen sätts variabeln running till sant och metoden move_dot kallas på. Sist i metoden move_dot finns raden self.after(50, self.move_dot) denna kallar på move_dot efter 1/20 sekund. Alltså kommer move_dot att köras varje 1/20 sekund. En funktion eller metod som kallar på sig själv kallas rekursiv. När användaren klickar på musen igen blir running falskt och metoden move_dot slutar att kalla på sig själv.

 En mask

Genom att skapa en lista av gröna punkter och deras positioner man göra en studsande mask:

Övning 3.10
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=400, height=300, bg="white")
        self.running=False
        self.bind("<Button-1>", self.start_stop)
        self.x=[10,20,30,40,50]
        self.y=[10,20,30,40,50]
        self.dx=[5,5,5,5,5]
        self.dy=[5,5,5,5,5]
        self.photo = PhotoImage(file="../greendot.gif")
        self.dot_id=[]
        for i in range(len(self.x)) :
            self.dot_id.append(self.create_image(self.x[i], self.y[i], image=self.photo))
        self.pack()
    
    def start_stop(self, event):
        if not self.running :
            self.running=True
            self.move_dot()
        else :
            self.running=False
        
    def move_dot(self):
        for i in range(len(self.dot_id)) :
            self.move(self.dot_id[i], self.dx[i], self.dy[i])
            self.x[i]=self.x[i]+self.dx[i]
            self.y[i]=self.y[i]+self.dy[i]
            if self.x[i] < 10 or self.x[i] > 390 : 
                self.dx[i]=-self.dx[i]
            if self.y[i] < 10 or self.y[i] > 290 : 
                self.dy[i]=-self.dy[i]
        if self.running :
            self.after(50, self.move_dot)

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


 Dra saker med musen

Genom att skilja på händelserna när man trycker ner och drar med musknappen nedtryckt kan man dra saker över en Canvas med musen. Programmet nedan använder också metoden find_closest för att välja den närmaste av de två punkterna.

Övning 3.11
Skriv och testa:

from tkinter import *


class Dot_Canvas(Canvas):
    
    def __init__(self, root):
        super().__init__(root, width=200, height=200, bg="white")
        self.dra_id=None
        self.dra_x=0
        self.dra_y=0
        self.bind("<ButtonPress-1>", self.ned)
        self.bind("<B1-Motion>", self.dra)
        self.photo = PhotoImage(file="../greendot.gif")
        self.create_image(40, 40, image=self.photo)
        self.create_image(160, 160, image=self.photo)
        self.pack()
    
    def ned(self, event):
        self.dra_id = self.find_closest(event.x, event.y)    
        self.dra_x=event.x
        self.dra_y=event.y
        
    def dra(self, event):
        dx=event.x-self.dra_x
        dy=event.y-self.dra_y
        self.move(self.dra_id, dx, dy)
        self.dra_x=event.x
        self.dra_y=event.y

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

Inlämningsuppgift 3.2
Skriv något av följande program och lämna in:

1) En analog klocka. Använd create_line och coords för att få visarna att vridas. Kan kompletteras med möjlighet att ställa klockan med musen.

2) Femtonspel - användaren klickar på den siffra hen vill flytta. Programmet utför flytten om det är möjligt och upptäcker om siffrorna är i rad.

3) Masken - Användaren styr en mask med knapp för sväng 90 grader höger eller vänster. Masken blir längre och längre. Man får inte krocka med väggar eller sig själv. Hinder kan införas och mm.