Search code examples
pythontkinterscale

Change element in ttk Style layout of Tkinter Scale


I have a question regarding ttk Styles. I'm applying a custom Style to the tkinter scale. Specifically, that means, I'm using a image as slider.

Now, I want to create three different scales, where the sliders are different in their coloring. I'm storing the three pyimages in a list self.slider = [pyimage0, pyimage1, pyimage2].

Starting the ttk styling with:

style = ttk.Style()

style.element_create('custom.Scale.trough', 'image', self.trough)
style.element_create('custom.Scale.slider', 'image', self.slider[0])

style.layout('custom.Horizontal.TScale',
              [('custom.Scale.trough', {'sticky': 'we'}),
               ('custom.Scale.slider',
                {'side': 'left', 'sticky': '',
                 'children': [('custom.Horizontal.Scale.label', {'sticky': ''})]
                })])
style.configure('custom.Horizontal.TScale', background='#ffffff')

Now I want to simply change through the colored sliders, when needed. However, how can I change the slider image after creating the element in style?

I tried with:

style.configure('custom.Horizontal.TScale.custom.Scale.slider', image=self.slider[i])

But it just stays on self.slider[0] for every scale.

Regards and thanks!!

EDIT

class CustomScale(ttk.Scale):
    def __init__(self, master=None, **kw):
        kw.setdefault("orient", "horizontal")
        self.variable = kw.pop('variable', DoubleVar(master))
        ttk.Scale.__init__(self, master, variable=self.variable, **kw)
        self._style_name = '{}.custom.{}.TScale'.format(self, kw['orient'].capitalize()) # unique style name to handle the text
        self['style'] = self._style_name

Solution

  • You need to define each style individually so they have there own unique names.

    The names are completely arbitrary and I had to use my own images but it works.

    I've expanded the answer to demonstrate usage.

    
    for i,a in enumerate(["red", "green", "blue"]):
    
        style.element_create(f'{a}.Scale.trough', 'image', self.trough)
        style.element_create(f'{a}.Scale.slider', 'image', self.slider[i])
    
        style.layout(f'{a}.Horizontal.TScale',
                      [(f'{a}.Scale.trough', {'sticky': 'we'}),
                       (f'{a}.Scale.slider',
                        {'side': 'left', 'sticky': '',
                         'children': [(f'{a}.Horizontal.Scale.label', {'sticky': ''})]
                        })])
        style.configure(f'{a}.Horizontal.TScale', background='#ffffff')
    
    self.redslider = ttk.Scale(self.master, from_ = 0, to=255, style = "red.Horizontal.TScale")
    self.redslider.grid(row = 0, column = 0, sticky = tk.NSEW)