如何设置Python Tkinter比例滑块的颜色?

时间:2020-01-08 09:08:14

标签: python python-3.x user-interface tkinter scale

我要设置滑块的颜色(箭头部分),我尝试仅使用-background的许多参数才能更改滑块的颜色。

enter image description here

但是当我使用-background时,滑块和背景会一起改变颜色,就像这样:

enter image description here

如果我将颜色设置为与背景色相同,则会导致找不到滑块。

如何设置滑块的颜色?

我的体重秤代码:

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)

2 个答案:

答案 0 :(得分:1)

要实现您想要的目标,我们必须使用ttk样式,因此我们需要使用ttk.Scale,但是,它不能接受您正在使用的tk.Scale的所有选项。因此,建议您使用ttkwidgets模块中的TickScale(请参阅文档here)。这样,您可以将tk.Scale选项与ttk样式结合使用。

想法是:

  1. 为滑块创建所需颜色的图像,例如与 tk.PhotoImage

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

    我使用了一个基本的矩形,但是如果您愿意,也可以加载更精美的图像。

  2. 创建彩色的滑块主题元素:

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

    我还使用了另一张图像img_slider_active,以在光标位于滑块上时突出显示滑块。

  3. 以自定义样式使用新元素

    style.layout('custom.Horizontal.TScale',
                 [('Horizontal.Scale.trough',
                   {'sticky': 'nswe',
                    'children': [('custom.Horizontal.Scale.slider',
                                  {'side': 'left', 'sticky': ''})]})])
    
  4. 将自定义样式应用于您的TickScale小部件。由于TickScale是基于ttk.Scale的,因此您需要使用样式来设置背景,前景色和低色选项,请参见下面的完整代码。
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()

答案 1 :(得分:1)

slider.configure(foreground=color)

在滑块周围绘制一个矩形,将其与槽区分开来。正如您所说,将前景色设置为与背景色相同会导致难以找到滑块。

另一种选择是使用不同的主题 (https://tkdocs.com/tutorial/styles.html)。下面的代码段可让您查看滑块在不同主题下的外观:

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        # root window
        self.title('Theme Demo')
        self.geometry('400x300')
        self.style = ttk.Style(self)

        # label
        label = ttk.Label(self, text='Name:')
        label.grid(column=0, row=0, padx=10, pady=10,  sticky='w')
        # scale
        slider = ttk.Scale(self, from_=1, to=10)
        slider.grid(column=1, row=0, padx=10, pady=10,  sticky='w')
        # button
        btn = ttk.Button(self, text='Show')
        btn.grid(column=2, row=0, padx=10, pady=10,  sticky='w')

        # radio button
        self.selected_theme = tk.StringVar()
        theme_frame = ttk.LabelFrame(self, text='Themes')
        theme_frame.grid(padx=10, pady=10, ipadx=20, ipady=20, sticky='w')


        for theme_name in self.style.theme_names():
            rb = ttk.Radiobutton(
                theme_frame,
                text=theme_name,
                value=theme_name,
                variable=self.selected_theme,
                command=self.change_theme)
            rb.pack(expand=True, fill='both')

    def change_theme(self):
        self.style.theme_use(self.selected_theme.get())


if __name__ == "__main__":
    app = App()
    app.mainloop()