Search code examples
pythonpython-3.xuser-interfacetkinterscale

How to set tkinter scale slider's color?


I want set slider color(arrow part), I try many parameter only -background can changed slider's color.

enter image description here

But slider and background will changed color together when I used -background, like this:

enter image description here

If I set color same with background color, It caused hard to find slider.

How to just set slider's color?

My scale code:

s2 = Scale(control_frame, from_=0, to=100, tickinterval=100, sliderrelief='flat', orient="horizontal", highlightthickness=0, background='black', fg='grey', troughcolor='#73B5FA', activebackground='#1065BF')
s2.place(x=70, y=600, anchor='nw', width = 280, height = 50)

Solution

  • To achieve what you want, we have to use a ttk style, so we need to use a ttk.Scale, however, it does not accept all the options of the tk.Scale you are using. Therefore, I suggest you to use the TickScale from the ttkwidgets module (See documentation here). This way you can combine the tk.Scale options with the ttk styling.

    The idea is to:

    1. create images of the desired color for the slider, e.g. with tk.PhotoImage:

      img_slider = tk.PhotoImage(width=30, height=15)
      img_slider.put("{<pixel_color> ... <pixel_color>} {<second line>} ...")
      

      I used a basic rectangle, but you can also load a more elaborated image if you wish.

    2. create the colored slider theme element:

      style.element_create('custom.Horizontal.Scale.slider', 'image', img_slider,
                           ('active', img_slider_active))
      

      I also used a different image img_slider_active, to highlight the slider when the cursor is on it.

    3. Use the new element in a custom style

      style.layout('custom.Horizontal.TScale',
                   [('Horizontal.Scale.trough',
                     {'sticky': 'nswe',
                      'children': [('custom.Horizontal.Scale.slider',
                                    {'side': 'left', 'sticky': ''})]})])
      
    4. Apply the custom style to your TickScale widget. Since the TickScale is based on a ttk.Scale, you need to use the style to set the background, foreground and troughcolor options, see full code below.
    import tkinter as tk
    from tkinter import ttk
    from ttkwidgets import TickScale
    
    def set_img_color(img, color):
        """Change color of PhotoImage img."""
        pixel_line = "{" + " ".join(color for i in range(img.width())) + "}"
        pixels = " ".join(pixel_line for i in range(img.height()))
        img.put(pixels)
    
    root = tk.Tk()
    # create images used for the theme
    slider_width = 30
    slider_height = 15
    # normal slider
    img_slider = tk.PhotoImage('img_slider', width=slider_width, height=slider_height, master=root)
    set_img_color(img_slider, "red")
    # active slider
    img_slider_active = tk.PhotoImage('img_slider_active', width=slider_width, height=slider_height, master=root)
    set_img_color(img_slider_active, '#1065BF')
    
    style = ttk.Style(root)
    style.theme_use('clam')
    # create scale element
    style.element_create('custom.Horizontal.Scale.slider', 'image', img_slider,
                         ('active', img_slider_active))
    # create custom layout
    style.layout('custom.Horizontal.TScale',
                 [('Horizontal.Scale.trough',
                   {'sticky': 'nswe',
                    'children': [('custom.Horizontal.Scale.slider',
                                  {'side': 'left', 'sticky': ''})]})])
    style.configure('custom.Horizontal.TScale', background='black', foreground='grey',
                    troughcolor='#73B5FA')
    scale = TickScale(root, from_=0, to=100, tickinterval=100, orient="horizontal",
                      style='custom.Horizontal.TScale')
    scale.pack(fill='x')
    root.mainloop()