使用PIL和Tkinter裁剪和显示图像

时间:2012-06-22 20:15:28

标签: python user-interface tkinter python-imaging-library crop

我在使用VB6永远被困后开始学习Python。为了帮助自己学习Tkinter的一些gui,我正在制作一个简单的老虎机。为了给车轮设置动画,我有一个~300x2000的图像,其中包含我打算用作条带的所有图片。现在约有6张照片。我只是一次显示部分图像(滚轮)以使其旋转。无论如何,我遇到了代码的一部分问题,我到了图像的末尾,需要从图像的末尾过渡到开始(轮子旋转,所以开始是底部和结束是顶部)。

出于某种原因,我无法正确裁剪和显示图像,即使我认为我的脚本在逻辑上有意义。我的代码发布在下面。您可以在300x2000左右的分辨率左右制作图像,以便用它来查看我遇到的问题。我的代码开始在我希望它显示的区域之外打印(在showsize变量之外),我无法找出原因。

非常感谢任何有关此问题的帮助。似乎作物没有足够短的缩短图像,但我发现的所有信息都让我觉得我的剧本应该工作得很好。我试图注释我的代码来解释发生了什么。

from Tkinter import *
from PIL import Image, ImageTk

def main():
    root = Tk()
    root.title = ("Slot Machine")
    canvas = Canvas(root, width=1500, height=800)
    canvas.pack()

    im = Image.open("colors.png")
    wheelw = im.size[0] #width of source image
    wheelh = im.size[1] #height of source image
    showsize = 400 #amount of source image to show at a time - part of 'wheel' you can see
    speed = 3 #spin speed of wheel
    bx1 = 250 #Box 1 x - where the box will appear on the canvas
    by = 250 #box 1 y
    numberofspins = 100  #spin a few times through before stopping

    cycle_period = 0  #amount of pause between each frame

    for spintimes in range(1,numberofspins):
        for y in range(wheelh,showsize,-speed):  #spin to end of image, from bottom to top

            cropped = im.crop((0, y-showsize, wheelw, y))  #crop which part of wheel is seen
            tk_im = ImageTk.PhotoImage(cropped)
            canvas.create_image(bx1, by, image=tk_im)  #display image

            canvas.update()                 # This refreshes the drawing on the canvas.
            canvas.after(cycle_period)       # This makes execution pause

        for y in range (speed,showsize,speed):  #add 2nd image to make spin loop
            cropped1 = im.crop((0, 0, wheelw, showsize-y)) #img crop 1
            cropped2 = im.crop((0, wheelh - y, wheelw, wheelh)) #img crop 2
            tk_im1 = tk_im2 = None
            tk_im1 = ImageTk.PhotoImage(cropped1)
            tk_im2 = ImageTk.PhotoImage(cropped2)

            #canvas.delete(ALL)
            canvas.create_image(bx1, by, image=tk_im2)  ###THIS IS WHERE THE PROBLEM IS..
            canvas.create_image(bx1, by + y, image=tk_im1)  ###PROBLEM

            #For some reason these 2 lines are overdrawing where they should be.  as y increases, the cropped img size should decrease, but doesn't

            canvas.update()                 # This refreshes the drawing on the canvas
            canvas.after(cycle_period)       # This makes execution pause

    root.mainloop()

if __name__ == '__main__':
    main()

1 个答案:

答案 0 :(得分:0)

如果不在每个周期重新创建图像,它会更简单,更快更顺畅。这是我使用canvas.move()的解决方案。请注意,我将canvas.create_image调用移到了for循环之外。我还将代码放在一个类中并添加了一个“旋转”按钮,并添加了一些东西以使其退出而没有错误。

from Tkinter import *
from PIL import Image, ImageTk
import sys

class SlotMachine():
    def __init__(self):
        root = Tk()
        root.title = ("Slot Machine")
        self.canvas = Canvas(root, width=1200, height=800)
        self.canvas.grid(column=0,row=0)
        button = Button(root, text="Spin!", width=20, command = self.spin)
        button.grid(column=0,row=1)

        self.alive = True
        root.protocol("WM_DELETE_WINDOW", self.die)
        root.mainloop()

    def spin(self):

        im = Image.open("colors.png")
        wheelw = im.size[0] #width of source image
        wheelh = im.size[1] #height of source image
        showsize = 400 # amount of source image to show at a time -
                       # part of 'wheel' you can see
        speed = 3 #spin speed of wheel
        bx1 = 250 #Box 1 x - where the box will appear on the canvas
        by = 250 #box 1 y
        numberofspins = 100  #spin a few times through before stopping
        cycle_period = 3  #amount of pause between each frame

        tk_im1 = ImageTk.PhotoImage(im)
        tk_im2 = ImageTk.PhotoImage(im)
        im1id = self.canvas.create_image(bx1, by + showsize, image=tk_im1)
        im2id = self.canvas.create_image(bx1, by + showsize + wheelh, 
                                         image=tk_im2)

        for spintimes in range(1,numberofspins):
            for y in range(wheelh,0,-speed): 
                if self.alive:

                    self.canvas.move(im1id, 0, -speed)
                    self.canvas.move(im2id, 0, -speed)

                    self.canvas.update() 
                    self.canvas.after(cycle_period)
                else:
                    sys.exit()

            self.canvas.move(im1id, 0, wheelh)
            self.canvas.move(im2id, 0, wheelh)

    def die(self):
        self.alive = False

if __name__ == '__main__':
    mySlotMachine = SlotMachine()

这会将车轮的一部分放在箱子外面,但你可以把你的老虎机纹理放在上面。