在我的项目中,我使用带有背景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
答案 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 >
结果几乎相同,但您必须实现两种方法来禁用和启用此“小部件”。这就是为什么我还在等待我的问题的解决方案。