Lime Scrollbar#
Horizontal Scrollbar#
The scrollbar consists of four parts, and each can have more than one state, so quite a few images.
Scrollbar Thumb#
Normal |
Pressed |
Active |
Disabled |
As seen in the Blue theme the scrollbar thumb/slider can be used as a common image for several other widgets. This aids us in ensuring that the various widgets have a recognisable theme look.
Even though the blue theme seems to have one of the more interesting thumbs, we may still be able to use some of the properties of the Ubuntu comboarrow, where the rounded corners look distinctly better. Also before applying a gradient let's see if we can add shadows and highlights with the light falling from the upper left to lower right.
- Select File Size
To assist centering make the file with an odd number of pixels . It is useful to see the results of the gradient and corners being created, so save the large image, which can be overwritten later.
- Construct the Border(s)
There was no need to explicitly draw the outside rectangle, our outer borders have been created by the background colour the central area being made into a gradient.
- Internal Fill/Gradient
Initially when making the gradient use its start and end colours as the internal corner fill. The paler corner fill colours may need a slight adjustment since the eye is more sensitive to the contrast. Later on a function was created that made this adjustment within a standard widget.
- Highlights and Shadows
Now for the highlights and shadows, our gradient should give the impression that the centre is raised therefore create a highlight on the upper and left sides. The hightlights did not work too well, even when made before resizing.
- Resize
Resize - normally with a Lanczos resampling filter.
- Complete the Corners
Make the corners transparent.
Now that is finished, we'd better see that it works before using it. If we need to reduce it in size then we'll have to rethink the corner sizes.
The final construct had four states, starting from the normal theme turn it upside down and we have the pressed state, lighten it and we have the active state finally turn it into greyscale and we have the disabled state. The vertical thumb was made by turning the horizontal thumb 90° to create the vertical normal state, then repeating the above actions to create the other three vertical states.
Scrollbar Trough and Arrows#
Normal |
Pressed |
Active |
Disabled |
The blue trough has no separate image, therefore it is being generated from the parent theme. Let's see if the result is acceptable.
Arrows share the same background image which is the thumb image.
Let's see if the alternative arrow can be used. Since the background is green be careful about the contrast with the 3 green arrow colours.
The first result is not too bad, the arrow and thumb have a good shape, the corners look nicely round but the thumb is about 50 as opposed to 30 pixels. The background gradient is a bit too sickly and was changed. The vertical size in a down arrow needs to match the combobox size, and as the arrow is longer than broad the border width could be reduced, the arrows were shoehorned into the background image.
Because the expected light source comes from the upper left corner the horizontal gradient had to be reversed, leaving the arrow colours as is. Ensure that the thumb gradient orientation allows it to expand without odd looking results - the arrows do not have a size change.
Once these three parts of the scrollbar have been finalised transpose each image to make the vertical scrollbars.
Show/Hide Code 10scrollbarthumb.py
'''
lime scrollbar thumb - used as template for other lime
widgets
First choice gradient start colour too sickly, the gradient
was then reversed.
'''
from PIL import Image
from roundrect import Gr_Base_Rect
from tools import trans
exp = 9 # enlargement, also thickness between rectangles
w=25
h=21
radius = 5 # gap size
second = 'white' #(102,153,204)
first = '#5D9B90'
startc = (222,247,222) #(143,188,143) (26,242,195)
fromci = (212,239,212)
stopc = (143,188,143) #(222,247,222) (225,242,238)
toci = (143,188,143) #(222,247,222) (210,242,234)
fout = '../images/lime/slider-hn.png'
tab = 0
Gr_Base_Rect(fout,w,h,exp,radius,first,second,startc,stopc,tab)
img = Image.open('../images/lime/slider-hn.png')
#rimg = img.rotate(90)
img.transpose(Image.ROTATE_90).save('../images/lime/slider-vn.png')
rimg = Image.open('../images/lime/slider-vn.png')
drimg = rimg.convert('L')
drimg = drimg.convert('RGBA')
trans(drimg,h,w,radius)
drimg.save('../images/lime/slider-vd.png')
#primg = img.rotate(270)
img.transpose(Image.ROTATE_270).save('../images/lime/slider-vp.png')
#primg.Image.open('../images/lime/slider-vp.png')
pimg = img.rotate(180)
pimg.save('../images/lime/slider-hp.png')
dimg = img.convert('L')
dimg = dimg.convert('RGBA')
trans(dimg,w,h,radius)
dimg.save('../images/lime/slider-hd.png')
aimg = img.point(lambda p: int(p * 1.1))
aimg.save('../images/lime/slider-ha.png')
arimg = rimg.point(lambda p: p * int(1.1))
arimg.save('../images/lime/slider-va.png')
Show/Hide Code 10scrollbararrow.py
'''
create right and up arrows
lime scrollbar thumb - used as template for other lime
widgets
'''
from PIL import Image, ImageDraw
from tools import transx
img = Image.open('../images/lime/slider-hn.png')
pimg = img
w, h = img.size
rdraw = ImageDraw.Draw(img)
pdraw = ImageDraw.Draw(pimg)
# draw right arrow
# upper surface lightest, lower surface darkest
light = 'GreenYellow'
med = 'LawnGreen'
border = '#5D9B90'
width = 17 #13
height = 17 #13
mid = 5 #4
st = (w - width) / 2, (h - height) / 2
rdraw.polygon([st[0],st[1],st[0]+mid,st[1]+(width-1)/2,
st[0],st[1]+(width-1)],fill=light)
rdraw.polygon([st,st[0]+(height-1),st[1]+(width-1)/2,
st[0]+mid,st[1]+(width-1)/2],fill=med)
rdraw.polygon([st[0],st[1]+(width-1),st[0]+(height-1),st[1]+(width-1)/2,
st[0]+mid,st[1]+(width-1)/2], fill=border)
img.save('../images/lime/arrowright-n.png')
aimg = img.point(lambda p: int(p * 1.1))
aimg.save('../images/lime/arrowright-a.png')
dimg = img.convert('L')
dimg = dimg.convert('RGBA')
transx(dimg,w,h)
dimg.save('../images/lime/arrowright-d.png')
img.transpose(Image.ROTATE_90).save('../images/lime/arrowup-n.png')
#uimg = img.rotate(90)
uimg = Image.open('../images/lime/arrowup-n.png')
auimg = uimg.point(lambda p: int(p * 1.1))
auimg.save('../images/lime/arrowup-a.png')
duimg = uimg.convert('L')
duimg = duimg.convert('RGBA')
transx(duimg,w,h)
duimg.save('../images/lime/arrowup-d.png')
pdraw.polygon([st[0],st[1],st[0]+mid,st[1]+(width-1)/2,
st[0],st[1]+(width-1)],fill=border)
pdraw.polygon([st,st[0]+(height-1),st[1]+(width-1)/2,
st[0]+mid,st[1]+(width-1)/2],fill=med)
pdraw.polygon([st[0],st[1]+(width-1),st[0]+(height-1),st[1]+(width-1)/2,
st[0]+mid,st[1]+(width-1)/2], fill=light)
pimg.save('../images/lime/arrowright-p.png')
#puimg = pimg.rotate(90)
pimg.transpose(Image.ROTATE_90).save('../images/lime/arrowup-p.png')
#puimg.save('../images/lime/arrowup-p.png')
img.transpose(Image.FLIP_LEFT_RIGHT).save('../images/lime/arrowleft-n.png')
pimg.transpose(Image.FLIP_LEFT_RIGHT).save('../images/lime/arrowleft-p.png')
limg = Image.open('../images/lime/arrowleft-n.png')
alimg = limg.point(lambda p: int(p * 1.1))
alimg.save('../images/lime/arrowleft-a.png')
dlimg = limg.convert('L')
dlimg = dlimg.convert('RGBA')
transx(dlimg,w,h)
dlimg.save('../images/lime/arrowleft-d.png')
#ndimg = img.rotate(270)
img.transpose(Image.ROTATE_270).save('../images/lime/arrowdown-n.png')
ndimg = Image.open('../images/lime/arrowdown-n.png')
adimg = ndimg.point(lambda p: int(p * 1.1))
adimg.save('../images/lime/arrowdown-a.png')
ddimg = ndimg.convert('L')
ddimg = ddimg.convert('RGBA')
transx(ddimg,w,h)
ddimg.save('../images/lime/arrowdown-d.png')
plimg = Image.open('../images/lime/arrowleft-p.png')
plimg.transpose(Image.ROTATE_90).save('../images/lime/arrowdown-p.png')
#drimg = plimg.rotate(90)
#drimg.save('../images/lime/arrowdown-p.png')
Show/Hide Code 10lime_scrollbar.py
'''
Original Scrollbar script.
Create theme extract for custom widgets, include state selection to view
the result of changing the state using different images and/or different
settings.
Setting the thumb ensure that the layout has expand 1 i.e.True, otherwise it
will not move in the trough. In turn the border must be large enough to ensure
that the image expands and does not create multiple images.
Grip is not included.
'''
from tkinter import Tk, PhotoImage, Listbox
from tkinter.ttk import Style, Frame, Scrollbar
from RunState import run_state
root = Tk()
fr = Frame(root)
fr.grid(column=0,row=0,sticky='nsew')
img3 = PhotoImage("slider-hn", file='../images/lime/slider-hn.png')
img4 = PhotoImage("slider-vn", file='../images/lime/slider-vn.png')
img5 = PhotoImage("slider-hd", file='../images/lime/slider-hd.png')
img6 = PhotoImage("slider-vd", file='../images/lime/slider-vd.png')
img7 = PhotoImage("slider-hp", file='../images/lime/slider-hp.png')
img8 = PhotoImage("slider-vp", file='../images/lime/slider-vp.png')
img9 = PhotoImage("arrowup-a", file='../images/lime/arrowup-a.png')
img10 = PhotoImage("arrowup-d", file='../images/lime/arrowup-d.png')
img11 = PhotoImage("arrowup-n", file='../images/lime/arrowup-n.png')
img12 = PhotoImage("arrowup-p", file='../images/lime/arrowup-p.png')
img13 = PhotoImage("arrowdown-a", file='../images/lime/arrowdown-a.png')
img14= PhotoImage("arrowdown-d", file='../images/lime/arrowdown-d.png')
img15 = PhotoImage("arrowdown-n", file='../images/lime/arrowdown-n.png')
img16 = PhotoImage("arrowdown-p", file='../images/lime/arrowdown-p.png')
img17 = PhotoImage("arrowleft-a", file='../images/lime/arrowleft-a.png')
img18= PhotoImage("arrowleft-d", file='../images/lime/arrowleft-d.png')
img19 = PhotoImage("arrowleft-n", file='../images/lime/arrowleft-n.png')
img20 = PhotoImage("arrowleft-p", file='../images/lime/arrowleft-p.png')
img21 = PhotoImage("arrowright-a", file='../images/lime/arrowright-a.png')
img22= PhotoImage("arrowright-d", file='../images/lime/arrowright-d.png')
img23 = PhotoImage("arrowright-n", file='../images/lime/arrowright-n.png')
img24 = PhotoImage("arrowright-p", file='../images/lime/arrowright-p.png')
img25 = PhotoImage("slider-ha", file='../images/lime/slider-ha.png')
img26 = PhotoImage("slider-va", file='../images/lime/slider-va.png')
style = Style()
# both theme_create and theme_settings worked
style.theme_create( "yummy", parent="clam", settings={
#style.theme_settings('default', {
# start of theme extract
"Horizontal.TScrollbar": {"layout": [
("Horizontal.Scrollbar.trough", { "children": # "sticky": "ew",
[("Horizontal.Scrollbar.leftarrow", {"side": "left"}),
("Horizontal.Scrollbar.rightarrow", {"side": "right"}),
("Horizontal.Scrollbar.thumb", {"side": "left","expand": 1,"sticky": "ew"})]
})]},
"Horizontal.Scrollbar.thumb": {"element create":
("image", 'slider-hn',
('disabled', 'slider-hd'),
('pressed', 'slider-hp'),
('active', 'slider-ha'),
{"border": 3}) #[9,2] , 'sticky': 'ew', 'padding': [7,2]
},
'Scrollbar.leftarrow': {"element create":
("image", 'arrowleft-n',
('disabled', 'arrowleft-d'),
('pressed', 'arrowleft-p'),
('active', 'arrowleft-a'),
{"border": 1})
},
'Scrollbar.rightarrow': {"element create":
("image", 'arrowright-n',
('disabled', 'arrowright-d'),
('pressed', 'arrowright-p'),
('active', 'arrowright-a'),
{"border": 1})
},
"Vertical.TScrollbar": {"layout": [
("Vertical.Scrollbar.trough", {"sticky": "ns", "children":
[("Vertical.Scrollbar.uparrow", {"side": "top"}),
("Vertical.Scrollbar.downarrow", {"side": "bottom"}),
("Vertical.Scrollbar.thumb", {"side": "top","expand": 1,"sticky": "ns"})]
})]},
"Vertical.Scrollbar.thumb": {"element create":
("image", 'slider-vn',
('disabled', 'slider-vd'),
('pressed', 'slider-vp'),
('active', 'slider-va'),
{"border": [2,9]})
},
'Scrollbar.uparrow': {"element create":
("image", 'arrowup-n',
('disabled', 'arrowup-d'),
('pressed', 'arrowup-p'),
('active', 'arrowup-a'),
{"border": 1})
},
'Scrollbar.downarrow': {"element create":
("image", 'arrowdown-n',
('disabled', 'arrowdown-d'),
('pressed', 'arrowdown-p'),
('active', 'arrowdown-a'),
{"border": 1})
},
'TCombobox': {
'configure': {'selectborderwidth': 1, 'padding': 2,
'insertwidth': 2, 'font': 'TkTextFont'}}
# end of theme extract - don't forget to add comma at end when inserting
})
style.theme_use('yummy') # 'default'
fr1 = Frame(fr,height=250,width=250)
fr1.grid(column=0,row=14,sticky='nsew')
widg = Scrollbar(fr1, orient="vertical")
widg1 = Scrollbar(fr1, orient="horizontal")
mylist = Listbox(fr1)
for line in range(100):
mylist.insert('end', "A really long line. "+ str(line)+" Line number " )
mylist.grid( column=0,row=0)
widg.grid(column=1,row=0,sticky='ns')
widg.configure( command = mylist.yview )
widg1.grid(column=0,row=1,sticky='ew')
widg1.configure( command = mylist.xview )
mylist.configure(yscrollcommand = widg.set, xscrollcommand = widg1.set) #
run_state(fr,widg,widg1)
root.mainloop()