如何禁用Tkinter画布对象

时间:2015-07-30 09:01:28

标签: python canvas tkinter base64

在我的项目中,我使用带有背景gif的Tkinter按钮作为图像。现在我需要添加一个"图标",作为base64字符串给出。 Tkinter Button没有提供添加图标或第二张图片的选项。这就是我使用canvas创建自定义按钮的原因。代码如下:

from Tkconstants import DISABLED
from Tkinter import Tk, Canvas
import Tkinter
import base64

import ImageTk


_FONTCOLOR = "#FFFFFF"
_BGCOLOR = "#787878"
_ICONDATA = '''iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZ
 G9iZSBJbWFnZVJlYWR5ccllPAAAAUJJREFUeNrsVc1qhDAQHq20FnRP7kF68iB9D+99Dp/J5+jdR9Bz8VwU
 PChbQbdo00yYLLuSrW4x9NKBjy+RL5nMZ34MxhjoDBM0h/YExoy3DCYnRtxx3BMbV8QTxxdVvaT7JGYWiV2
 OPbE1GywH9RwDh83xqEiCupHjg6Mmnixa+T5JkrelmuM4fimK4nVJF4bhM6cjLkqWu1vp69P8Q9u2MI7j/P
 OO5hV+yn9wEVEUqRI8yAZOmuc5NE0DWZbBMAznupN95o276KQryxI8z4MgCMD3fajrWqn79Tnoug5c1xVtZ
 LRq04Om8H3bBI7jQN/3oo2M/U0ToO9VVQlrkLH/UwJ2y/HHsG0b97vYRcjYV+mss5N6EWmaqhIc5zZdsWaS
 SUzqHFZW8L5Sd5CLNqgKbXeR9ttU/3vw/yb/eYJvAQYA4v5708p9noAAAAAASUVORK5CYII='''


class DesktopBtn(Tkinter.Button):

    def __init__(self, parent, buttonName, connector=None, **options):
        '''
        @param buttonName: Name of the button

        '''
        Tkinter.Button.__init__(self, parent, **options)
        self._imagePath = 'button.gif'
        self._BtnPresspath = 'buttonP.gif'
        self._BtnPressImage = Tkinter.PhotoImage(file=self._BtnPresspath)
        self._image = Tkinter.PhotoImage(file=self._imagePath)
        self.bind('<ButtonPress-1>', self._on_pressed)
        self.bind('<ButtonRelease-1>', self._on_release)
        self._parent = parent
        self._btnName = buttonName
        self._connector = connector
        self.config(width=70,
                    height=65,
                    borderwidth=0,
                    compound=Tkinter.CENTER,
                    font=("Arial", 9, "bold"),
                    foreground=_FONTCOLOR,
                    activebackground=_BGCOLOR,
                    text=buttonName,
                    wraplength=64,
                    image=self._image,
                    command=self._onClickSwitch,
                    state="disabled")

    def _on_pressed(self, event):
        if self.cget("state") != "disabled":
            self.config(relief="flat")
            self.config(image=self._BtnPressImage)

    def _on_release(self, event):
        if self.cget("state") != "disabled":
            self.config(image=self._image)

    def _onClickSwitch(self):
        self.config(relief="flat")
        if self._connector:
            self._connector.switchDesktop(self._btnName,
                                          "test")

    def getButtonName(self):
        return self._btnName

    def setConnector(self, connector):
        self._connector = connector


class CustomButton(Canvas):
    def __init__(self, parent, buttonname=None, icon=None, command=None):
        Canvas.__init__(self, parent, borderwidth=0, highlightthickness=0)
        self.command = command
        self._imagePath = 'button.gif'
        self._BtnPresspath = 'buttonP.gif'
        self._icon = icon
        self._BtnPressImage = Tkinter.PhotoImage(file=self._BtnPresspath)
        self._image = Tkinter.PhotoImage(file=self._imagePath)
        self.bgimage = self.create_image(35, 35, image=self._image)
        self.text = buttonname
        if self._icon:
            self._icondata = base64.b64decode(self._icon)
            self._iconimage = ImageTk.PhotoImage(data=self._icondata)
            self.create_image(35, 35, image=self._iconimage)
        if self.text and self._icon:
            self.create_text(35, 63, anchor="s",
                             state=DISABLED,
                             text=self.text,
                             font=("arial", 9, "bold"),
                             fill=_FONTCOLOR)
        elif not self._icon:
            self.create_text(35, 45, anchor="s",
                             state=DISABLED,
                             text=self.text,
                             font=("arial", 9, "bold"),
                             fill=_FONTCOLOR)
        self.configure(width=70, height=70, state=DISABLED)
#         if self.cget("state") == "disabled":
#             pass
#         else:
        self.bind("<ButtonPress-1>", self._on_press)
        self.bind("<ButtonRelease-1>", self._on_release)

    def _on_press(self, event):
        self.itemconfig(self.bgimage,image=self._BtnPressImage)
        print "pressed"

    def _on_release(self, event):
        self.itemconfig(self.bgimage,image=self._image)
        if self.command is not None:
            self.command()

tk = Tk()
but = DesktopBtn(tk, "test")
but.pack()
butt_blank = CustomButton(tk)
butt_text = CustomButton(tk, buttonname="test")
butt_icon = CustomButton(tk, icon=_ICONDATA)
butt_icon_text = CustomButton(tk, icon=_ICONDATA, buttonname="test")
butt_blank.pack()
butt_text.pack()
butt_icon.pack()
butt_icon_text.pack()
tk.mainloop()

第一个按钮(类)是我以前使用的Tkinter按钮。现在我只有问题。如何禁用我的画布自定义按钮,就像普通的Tkinter Button一样。它应该是灰色的并忽略鼠标事件。 根据{{​​3}}在create_image或甚至canvas对象上使用DISABLED状态,我的自定义Button应该像旧Button一样。我使用的是Python 2.7。

以下是使用的按钮图像(button.gif和buttonP.gif):Tkinter 8.5 reference button.gif

2 个答案:

答案 0 :(得分:1)

如评论中所述,一种解决方法是制作合成图像 一个简单的例子是:

#!python3

import tkinter as tk
from PIL import Image, ImageTk

root = tk.Tk()
bgim = Image.open("bg.gif")
bgphoto = ImageTk.PhotoImage(bgim)

button1 = tk.Button(root, image=bgphoto)
button1.pack()

newim = Image.open("bg.gif").convert('RGBA') # ensure both images are in a mode that supports transparency
iconim = Image.open("Icon.png").convert('RGBA')
newim.paste(iconim, (-30,-40), iconim) # paste second image into first image
newphoto = ImageTk.PhotoImage(newim)
button2 = tk.Button(root, image=newphoto)
button2.pack()

root.mainloop()

bg.gif是来自原始帖子的图片之一,另一个是带有透明度的简单png图标。

有关合并图片的详细信息,请参阅此post

答案 1 :(得分:0)

以下是另一种解决方法,它在其他项目之上绘制rectangle,在我的示例stipple中用白色填充Bitmap并在gray50填充self.create_rectangle(-1,-1,70,70, stipple="gray50", fill="white")from Tkconstants import DISABLED, NORMAL from Tkinter import Tk, Canvas import Tkinter import base64 import ImageTk _FONTCOLOR = "#FFFFFF" _BGCOLOR = "#787878" _ICONDATA = '''iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAGXRFWHRTb2Z0d2FyZQBBZ G9iZSBJbWFnZVJlYWR5ccllPAAAAUJJREFUeNrsVc1qhDAQHq20FnRP7kF68iB9D+99Dp/J5+jdR9Bz8VwU PChbQbdo00yYLLuSrW4x9NKBjy+RL5nMZ34MxhjoDBM0h/YExoy3DCYnRtxx3BMbV8QTxxdVvaT7JGYWiV2 OPbE1GywH9RwDh83xqEiCupHjg6Mmnixa+T5JkrelmuM4fimK4nVJF4bhM6cjLkqWu1vp69P8Q9u2MI7j/P OO5hV+yn9wEVEUqRI8yAZOmuc5NE0DWZbBMAznupN95o276KQryxI8z4MgCMD3fajrWqn79Tnoug5c1xVtZ LRq04Om8H3bBI7jQN/3oo2M/U0ToO9VVQlrkLH/UwJ2y/HHsG0b97vYRcjYV+mss5N6EWmaqhIc5zZdsWaS SUzqHFZW8L5Sd5CLNqgKbXeR9ttU/3vw/yb/eYJvAQYA4v5708p9noAAAAAASUVORK5CYII=''' class DesktopBtn(Tkinter.Button): def __init__(self, parent, buttonName, connector=None, **options): ''' @param buttonName: Name of the button ''' Tkinter.Button.__init__(self, parent, **options) self._imagePath = 'button.gif' self._BtnPresspath = 'buttonP.gif' self._BtnPressImage = Tkinter.PhotoImage(file=self._BtnPresspath) self._image = Tkinter.PhotoImage(file=self._imagePath) self.bind('<ButtonPress-1>', self._on_pressed) self.bind('<ButtonRelease-1>', self._on_release) self._parent = parent self._btnName = buttonName self._connector = connector self.config(width=70, height=65, borderwidth=0, compound=Tkinter.CENTER, font=("Arial", 9, "bold"), foreground=_FONTCOLOR, activebackground=_BGCOLOR, text=buttonName, wraplength=64, image=self._image, command=self._onClickSwitch ) def _on_pressed(self, event): if self.cget("state") != "disabled": self.config(relief="flat") self.config(image=self._BtnPressImage) def _on_release(self, event): if self.cget("state") != "disabled": self.config(image=self._image) def _onClickSwitch(self): self.config(relief="flat") if self._connector: self._connector.switchDesktop(self._btnName, "test") def getButtonName(self): return self._btnName def setConnector(self, connector): self._connector = connector class CustomButton(Tkinter.Canvas): def __init__(self, parent, buttonname=None, icon=None, command=None, **options): Tkinter.Canvas.__init__(self, parent, borderwidth=0, highlightthickness=0,**options) self.command = command self._imagePath = 'button.gif' self._BtnPresspath = 'buttonP.gif' self._icon = icon self._BtnPressImage = Tkinter.PhotoImage(file=self._BtnPresspath) self._image = Tkinter.PhotoImage(file=self._imagePath) self.bgimage = self.create_image(35, 35, image=self._image) self.text = buttonname if self._icon: self._icondata = base64.b64decode(self._icon) self._iconimage = ImageTk.PhotoImage(data=self._icondata) self.create_image(35, 35, image=self._iconimage) if self.text and self._icon: self.create_text(35, 63, anchor="s", text=self.text, font=("arial", 8, "bold"), fill=_FONTCOLOR) elif not self._icon: self.create_text(35, 45, anchor="s", text=self.text, font=("arial", 8, "bold"), fill=_FONTCOLOR) self.configure(width=70, height=70) self._activation() def disable(self): self.config(state=DISABLED) self._activation() def enable(self): self.config(state=NORMAL) self._activation() def _activation(self): if self.cget("state") == "disabled": self.create_rectangle(-1,-1,70,70, stipple="gray50", fill="white") self.unbind("<ButtonPress-1>") self.unbind("<ButtonRelease-1>") else: self.bind("<ButtonPress-1>", self._on_press) self.bind("<ButtonRelease-1>", self._on_release) def _on_press(self, event): self.itemconfig(self.bgimage, image=self._BtnPressImage) print "pressed" def _on_release(self, event): self.itemconfig(self.bgimage, image=self._image) if self.command is not None: self.command() tk = Tk() but = DesktopBtn(tk, "test") but.config(state="disabled") but.pack() butt_blank = CustomButton(tk) butt_text = CustomButton(tk, buttonname="test", state=DISABLED) butt_icon = CustomButton(tk, icon=_ICONDATA) butt_icon_text = CustomButton(tk, icon=_ICONDATA, buttonname="test") butt_blank.pack() butt_text.pack() butt_icon.pack() butt_icon_text.disable() butt_icon_text.pack() tk.mainloop()

这就是代码的样子:

                          < Thursday July 30 2015 >   

结果几乎相同,但您必须实现两种方法来禁用和启用此“小部件”。这就是为什么我还在等待我的问题的解决方案。