# Author: Miguel Martinez Lopez
#
# Uncomment the next line to see my email
# print("Author's email: %s"%"61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex"))
# PIL is more efficient manipulating directly pixels than PhotoImage. See this discussion:
# https://groups.google.com/forum/#!topic/comp.lang.python/nQ6YO-dTz10
#
# To install PIL on windows for Python 3, read this:
# http://stackoverflow.com/questions/7407185/pil-for-python-3-2-on-windows-or-alternatives
#
# To install ImageTk for Python 2.7 on ubuntu do:
# sudo apt-get install python-imaging-tk
# and for Python 3:
# sudo apt-get install python3-pil.imagetk
#
try:
from Tkinter import Canvas
from Tkconstants import *
except ImportError:
from tkinter import Canvas
from tkinter.constants import *
from PIL import Image, ImageDraw, ImageTk
# Python 2/3 compatibility
try:
basestring
except NameError:
basestring = str
def hex2rgb(str_rgb):
try:
rgb = str_rgb[1:]
if len(rgb) == 6:
r, g, b = rgb[0:2], rgb[2:4], rgb[4:6]
elif len(rgb) == 3:
r, g, b = rgb[0] * 2, rgb[1] * 2, rgb[2] * 2
else:
raise ValueError()
except:
raise ValueError("Invalid value %r provided for rgb color."
% str_rgb)
return tuple(int(v, 16) for v in (r, g, b))
class GradientFrame(Canvas):
def __init__(self, master, from_color, to_color, width=None, height=None, orient=HORIZONTAL, steps=None):
Canvas.__init__(self, master)
if steps is None:
if orient == HORIZONTAL:
steps = height
else:
steps = width
if isinstance(from_color, basestring):
from_color = hex2rgb(from_color)
if isinstance(to_color, basestring):
to_color = hex2rgb(to_color)
r,g,b = from_color
dr = float(to_color[0] - r)/steps
dg = float(to_color[1] - g)/steps
db = float(to_color[2] - b)/steps
if orient == HORIZONTAL:
if height is None:
raise ValueError("height can not be None")
self.configure(height=height)
width = self.winfo_screenwidth()
image = Image.new("RGB", (width, height), "#FFFFFF")
draw = ImageDraw.Draw(image)
for i in range(steps):
r,g,b = r+dr, g+dg, b+db
y0 = int(float(height * i)/steps)
y1 = int(float(height * (i+1))/steps)
draw.rectangle((0, y0, width, y1), fill=(int(r),int(g),int(b)))
else:
if width is None:
raise ValueError("width can not be None")
self.configure(width=width)
height = self.winfo_screenheight()
image= Image.new("RGB", (width, height), "#FFFFFF")
draw = ImageDraw.Draw(image)
for i in range(steps):
r,g,b = r+dr, g+dg, b+db
x0 = int(float(width * i)/steps)
x1 = int(float(width * (i+1))/steps)
draw.rectangle((x0, 0, x1, height), fill=(int(r),int(g),int(b)))
self._gradient_photoimage = ImageTk.PhotoImage(image)
self.create_image(0, 0, anchor=NW, image=self._gradient_photoimage)
if __name__ == "__main__":
try:
from Tkinter import Tk, Label
except ImportError:
from tkinter import Tk, Label
root = Tk()
Label(root, text="Gradient 1:").pack(anchor=W)
GradientFrame(root, from_color="#000000", to_color="#E74C3C", height=100).pack(fill=X)
Label(root, text="Gradient 2 (GTK gradient):").pack(anchor=W, pady=(20,0))
GradientFrame(root, from_color="#FCFCFC", to_color="#E2E2E2", height=30).pack(fill=X, pady=(0,10))
root.mainloop()
Diff to Previous Revision
--- revision 1 2017-03-11 02:23:01
+++ revision 2 2017-03-11 02:29:23
@@ -63,11 +63,11 @@
to_color = hex2rgb(to_color)
r,g,b = from_color
- dr = float(to_color[0] - from_color[0])/steps
- dg = float(to_color[1] - from_color[1])/steps
- db = float(to_color[2] - from_color[2])/steps
+ dr = float(to_color[0] - r)/steps
+ dg = float(to_color[1] - g)/steps
+ db = float(to_color[2] - b)/steps
- if orient == HORIZONTAL:
+ if orient == HORIZONTAL:
if height is None:
raise ValueError("height can not be None")