将图像绘制到tkinter画布上

时间:2016-03-23 15:15:41

标签: python image tkinter tkinter-canvas

我已经搜索过但没有发现这个话题,所以我会在这里问。

我开始开发非常基本的游戏,我想在我的背景中加载一张图片。我在Python上使用电子书来帮助我这样做,并且根据它,以下代码是正确的:

from tkinter import *
import time
import random

Width = 1000
Height = (Width/12)*9

class Game:

    def __init__(self):
        self.tk = Tk()
        self.tk.title("Monster Rush")
        self.tk.resizable(0, 0)
        self.tk.wm_attributes("-topmost", 1)
        self.canvas = Canvas(self.tk, width=Width, height=Height, highlightthickness=0)
        self.canvas.pack()
        self.tk.update()
        self.canvas_height = 500
        self.canvas_width = 500
        self.bg = PhotoImage(file="anipedra.gif")
        w = self.bg.width()
        h = self.bg.height()
        for x in range(0, 5):
            for y in range(0, 5):
                self.canvas.create_image(x * w, y * h, image=self.bg, anchor='nw')
        self.sprites = []
        self.running = True

    def mainloop(self):
        while 1:
            if self.running == True:
                for sprite in self.sprites:
                    sprite.move()
                    self.tk.update_idletasks()
        self.tk.update()
        time.sleep(0.01)

class Enemy(Game):
    def __init__(self):
        self.e = Game()
        self.e.mainloop()

class Player(Game):
    def __init__(self):
        self.e = Game()
        self.e.mainloop()

Troll = Enemy()
Grunt = Enemy()
Minion = Enemy()
Player = Player()

但每次我都这样做:

  1. 如果是.gif,IDLE通常会显示:
  2.   Traceback (most recent call last):
        File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 47, in <module>
      Troll = Enemy()
        File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 39, in __init__
      self.e = Game()
        File "C:\Users\Nuno\Desktop\Python\Projectos\Monster Rush\Monster Rush (T.D.).py", line 20, in __init__
      self.bg = PhotoImage(file="background.gif")
        File "C:\Users\Nuno\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 3393, in __init__
      Image.__init__(self, 'photo', name, cnf, master, **kw)
        File "C:\Users\Nuno\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 3349, in __init__
      self.tk.call(('image', 'create', imgtype, name,) + options)
      _tkinter.TclError: couldn't recognize data in image file "background.gif"
    
    1. 如果是上述代码(或任何其他格式)中的.gif:

      文件停止响应并崩溃。

    2. 任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:2)

堆栈跟踪中的错误表明该文件实际上不是GIF文件。你确定它实际上是一个gif文件,还是某个其他人重命名为.gif作为后缀的文件?

您还有几个关键的设计缺陷。

  1. 在精心设计的tkinter应用程序中,您必须始终只有一个根窗口。你创造了四个(或八个......) - 每个玩家和敌人对象一个。

  2. 您的类都继承自Game并自行创建Game实例。这绝对没有意义。要么继承游戏,要么创建一个实例,但不要同时做这两件事。但是,由于Game创建了一个根窗口,因此创建多个Game对象毫无意义。

  3. 您没有正确使用事件循环。你永远不会让tkinter处理某些事件。你有自己的无限循环,你可以在其中调用update_idletasks(),但它只处理屏幕刷新和其他&#34;空闲&#34;事件。它不会处理按键或鼠标点击。你调用update但它在无限循环之外,所以它永远不会被调用。

    1. 作为一般经验法则,您不应该在GUI中调用sleep。它完全符合它所说的:它让你的应用程序进入睡眠状态。虽然它在睡觉但它不会刷新屏幕并且它不会处理鼠标或键盘事件。应用程序真的死了。
  4. 虽然我不确切地知道你的意图是什么,但你可以重写自己的自定义mainloop以通过这样的方式利用真实的事件循环:

    def mainloop(self): 
        if self.running == True: 
            for sprite in self.sprites: 
                sprite.move() 
            self.tkafter(30, self.mainloop)
    

    您需要设置30来表示您希望显示更新的速度。该值以毫秒为单位,因此30表示30fps。此外,您需要只调用根窗口的mainloop函数一次,以便它可以处理事件。

答案 1 :(得分:0)

也许这个!某些图像软件可以并且有时会将扩展名结尾更改为图像文件。他们可以根据需要利用扩展资本。例如.gif到.GIF或jpeg到JPEG等。在将文件上传到网站之前,你不会意识到这一点,然后你会看到大写的扩展。谷歌臭名昭着的Picaso下载到我的电脑,我不得不做一个重新系统安装来修复它。没有关系,但Windows在一些较旧的XP版本中也保密地改变了jpeg格式。让别人在另一台机器上测试你的代码。