简体   繁体   English

在 tkinter 中更改滚动条的外观(使用 ttk 样式)

[英]Changing the appearance of a Scrollbar in tkinter (using ttk styles)

I was wondering if you could help me with a style options issue in ttk.我想知道你是否可以帮助我解决 ttk 中的样式选项问题。 I've managed to change most of the basic ttk widgets to the style of my preference.我已经设法将大部分基本的 ttk 小部件更改为我喜欢的样式。 I'm only stuck at changing the style of a scrollbar.我只是停留在改变滚动条的样式上。 I've searched for hours looking for an answer, unfortunately to no avail.我已经搜索了几个小时寻找答案,不幸的是无济于事。

Here's a sample code using the scrollbar style option:下面是使用滚动条样式选项的示例代码:

import tkinter as tk                 
from tkinter import ttk

class Gui:
    def __init__(self,mainframe):

        #set the style
        style = ttk.Style()
        style.configure('Horizontal.TScrollbar',background = "blue" )   

        #Create a mainframe
        self.mainframe = mainframe
        self.mainframe.title("example")


        #creating scrollbar frame
        scrl_attr_frame = ttk.Frame(self.mainframe)                            
        scrl_attr_frame.grid(column=0,row=5,sticky="ns")                                           
        scrl_attr_frame.rowconfigure(0, weight=1)                                                   
        attr_canvas = tk.Canvas(scrl_attr_frame)                                                   
        h_scroll = ttk.Scrollbar(scrl_attr_frame,orient="horizontal", command=attr_canvas.xview)
        attr_canvas.configure(xscrollcommand=h_scroll.set)                                       
        attr_canvas.grid(column=0,row=0,sticky="ns")                                                                            
        h_scroll.grid(column=0, row=1,sticky="we") 
        attr_frame = ttk.Frame(attr_canvas)                                                        
        attr_frame.grid(column=0,row=0,sticky="ns")                                                 
        attr_canvas.create_window((0,0),window=attr_frame, anchor='nw')
        attr_frame.bind("<Configure>",lambda event, canvas=attr_canvas : canvas.configure(scrollregion=canvas.bbox("all"),width=200,height=200,takefocus=False,highlightthickness=0))#attribute_frame.winfo_height()/20,highlightthickness=0))

        #setup treeview widget
        tree_columns = ("c1", "c2", "c3")

        self.tree = ttk.Treeview(attr_frame,columns=tree_columns, show="headings",takefocus=False)
        self.tree.grid(column=0, row=0, sticky='nsew')

        for head in tree_columns:
            self.tree.heading(head,text=head,anchor="w")


root = tk.Tk()
myapp = Gui(root)
root.mainloop()

I also tried several combinations including;我还尝试了几种组合,包括;

style.configure('TScrollbar',background='blue') 

#and
style.configure('CustomScroll.Horizontal.TScrollbar',background='blue')

#in combination with
h_scroll = ttk.Scrollbar(scrl_attr_frame,orient="horizontal", command=attr_canvas.xview)
h_scroll['style'] = "CustomScroll.Horizontal.TScrollbar" 

Many thanks for your help!非常感谢您的帮助!

It looks like you just want to change the trough for a horizontal scrollbar under the Windows theme. 看起来您只想更改Windows主题下水平滚动条的槽。 The ttk widgets are constructed from a set of elements provided by a styling engine and combined using the declared layout. ttk小部件由样式引擎提供的一组元素构成,并使用声明的布局进行组合。 Under Windows the styling engine is the Windows Visual Styles API which means the programmer doesn't have any control over the colours or images used to draw most of the common elements. 在Windows下,样式引擎是Windows Visual Styles API,这意味着程序员无法控制用于绘制大多数常见元素的颜色或图像。 The button background, scrollbar trough and buttons and the thumb and even the grip drawn inside the scrollbar thumb are all provided by Windows. 按钮背景,滚动条槽和按钮以及拇指甚至滚动条拇指内绘制的手柄都由Windows提供。

It is possible to take control of this for application customization but at a cost of making your application no longer look standard on the given platform. 可能采取的这种控制应用程序的定制,但在让你的应用程序不再看给定的平台上标准的成本。 To do this you have to provide your own UI elements and define new widget layouts. 为此,您必须提供自己的UI元素并定义新的窗口小部件布局。 Ultimately this can turn into defining your own theme. 最终,这可以转变为定义自己的主题。 The tcl scripts in the ttk library provide good examples to follow and there are even some complete (if old) themes using bitmaps to declare image based theme elements in the original version of ttk which was called 'tile'. ttk库中的tcl脚本提供了很好的示例,甚至还有一些完整的(如果旧的)主题使用位图来声明原始版本的ttk中基于图像的主题元素,这被称为“tile”。

In this specific example to get a Windows horizontal scrollbar with a custom coloured background we need to redefine the layout to use the scrollbar trough from the Tk drawn elements. 在这个具有自定义彩色背景的Windows水平滚动条的具体示例中,我们需要重新定义布局以使用Tk绘制元素中的滚动条槽。 The elements used in the 'default' theme can be copied in and are defined using style configuration parameters and are then drawn by Tk itself and not passed off to a third party engine. “默认”主题中使用的元素可以复制并使用样式配置参数定义,然后由Tk本身绘制,而不是传递给第三方引擎。 The following code generates a scrollbar like this which uses the standard buttons and thumb provided by the vsapi styling engine but replaces the trough. 下面的代码生成一个这样的滚动条,它使用vsapi样式引擎提供的标准按钮和拇指,但替换了槽。 This imported trough understands the troughcolor style configuration option and so we can define a colour to use now. 这个导入的槽了解troughcolor样式配置选项,因此我们可以定义一个现在使用的颜色。 All scrollbars using this style will use the same colour as the widget itself will not accept a troughcolor option. 使用此样式的所有滚动条将使用相同的颜色,因为窗口小部件本身将不接受troughcolor选项。 ie: you can't have one scrollbar be blue and another be red unless you define a new style for each new colour. 即:除非为每种新颜色定义新样式,否则不能有一个滚动条为蓝色而另一个滚动条为红色。

在此输入图像描述

from tkinter import *
from tkinter.ttk import *

def main():
    app = Tk()
    style = Style()

    # import the 'trough' element from the 'default' engine.
    style.element_create("My.Horizontal.Scrollbar.trough", "from", "default")

    # Redefine the horizontal scrollbar layout to use the custom trough.
    # This one is appropriate for the 'vista' theme.
    style.layout("My.Horizontal.TScrollbar",
        [('My.Horizontal.Scrollbar.trough', {'children':
            [('Horizontal.Scrollbar.leftarrow', {'side': 'left', 'sticky': ''}),
             ('Horizontal.Scrollbar.rightarrow', {'side': 'right', 'sticky': ''}),
             ('Horizontal.Scrollbar.thumb', {'unit': '1', 'children':
                 [('Horizontal.Scrollbar.grip', {'sticky': ''})],
            'sticky': 'nswe'})],
        'sticky': 'we'})])
    # Copy original style configuration and add our new custom configuration option.
    style.configure("My.Horizontal.TScrollbar", *style.configure("Horizontal.TScrollbar"))
    style.configure("My.Horizontal.TScrollbar", troughcolor="red")

    # Create and show a widget using the custom style
    hs = Scrollbar(app, orient="horizontal", style="My.Horizontal.TScrollbar")
    hs.place(x=5, y=5, width=150)
    hs.set(0.2,0.3)

    app.mainloop()

if __name__ == '__main__':
    main()

It's easier if you use the clam theme: 如果你使用clam主题更容易:

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
style = ttk.Style()
style.theme_use('clam')

# list the options of the style
# (Argument should be an element of TScrollbar, eg. "thumb", "trough", ...)
print(style.element_options("Horizontal.TScrollbar.thumb"))

# configure the style
style.configure("Horizontal.TScrollbar", gripcount=0,
                background="Green", darkcolor="DarkGreen", lightcolor="LightGreen",
                troughcolor="gray", bordercolor="blue", arrowcolor="white")

hs = ttk.Scrollbar(root, orient="horizontal")
hs.place(x=5, y=5, width=150)
hs.set(0.2,0.3)

root.mainloop()

This does not appear to be possible in tkinter on Windows. 这在Windows上的tkinter中似乎不可能。 The below answer says so: ScrolledText Scrollbar Color (Python Tkinter) 下面的答案是这样说的: ScrolledText Scrollbar Color(Python Tkinter)

Scrollbar documentation: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/scrollbar.html Supported style fields: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/ttk-Scrollbar.html 滚动条文档: http//infohost.nmt.edu/tcc/help/pubs/tkinter/web/scrollbar.html支持的样式字段: http//infohost.nmt.edu/tcc/help/pubs/tkinter/web/ TTK-Scrollbar.html

I tried passing both 'background' and 'troughcolor' unsuccessfully on my Windows machine. 我尝试在我的Windows机器上传递'background'和'troughcolor'失败。 I also tried applying the style to the general scrollbar: style.configure('TScrollbar', background="blue") None of my solutions worked. 我也尝试将样式应用于常规滚动条:style.configure('TScrollbar',background =“blue”)我的解决方案都没有用。

Also another forum post agrees that you can't style the scrollbar background here: http://www.gossamer-threads.com/lists/python/python/822292 另外一篇论坛帖子同意你不能在这里设置滚动条背景的样式: http//www.gossamer-threads.com/lists/python/python/822292

Here's a stand-alone solution - works for both horizontal and vertical scrollbars.这是一个独立的解决方案 - 适用于水平和垂直滚动条。


def make_scrollbar_styles(
        troughcolor='black',
        background='grey',
        arrowcolor='white',
) -> Tuple[str, str]:
    """
    Style the scrollbars.  Usage:
        parent_frame = ... # tk.Frame(...) or tk.Tk() or whatever you're using for the parent
        hstyle, vstyle = make_scrollbar_styles()
        self._vbar = ttk.Scrollbar(parent_frame, orient='vertical', style=vstyle)
        self._hbar = ttk.Scrollbar(parent_frame, orient='horizontal', style=hstyle)
    """
    style = Style()

    for is_hori in (True, False):
        v = "Horizontal" if is_hori else "Vertical"
        style.element_create(f'CustomScrollbarStyle.{v}.Scrollbar.trough', 'from', 'default')
        style.element_create(f'CustomScrollbarStyle.{v}.Scrollbar.thumb', 'from', 'default')
        style.element_create(f'CustomScrollbarStyle.{v}.Scrollbar.leftarrow', 'from', 'default')
        style.element_create(f'CustomScrollbarStyle.{v}.Scrollbar.rightarrow', 'from', 'default')
        style.element_create(f'CustomScrollbarStyle.{v}.Scrollbar.grip', 'from', 'default')
        style.layout(
            f'CustomScrollbarStyle.{v}.TScrollbar',
            [(f'CustomScrollbarStyle.{v}.Scrollbar.trough', {
                'children': [
                    # Commenting in these 2 lines adds arrows (at least horizontally)
                    # (f'CustomScrollbarStyle.{v}.Scrollbar.leftarrow', {'side': 'left', 'sticky': ''}) if is_hori else (f'CustomScrollbarStyle.{v}.Scrollbar.uparrow', {'side': 'top', 'sticky': ''}),
                    # (f'CustomScrollbarStyle.{v}.Scrollbar.rightarrow', {'side': 'right', 'sticky': ''})  if is_hori else (f'CustomScrollbarStyle.{v}.Scrollbar.downarrow', {'side': 'bottom', 'sticky': ''}),
                    (f'CustomScrollbarStyle.{v}.Scrollbar.thumb', {
                        'unit': '1',
                        'children': [(f'CustomScrollbarStyle.{v}.Scrollbar.grip', {'sticky': ''})],
                        'sticky': 'nswe'}
                     )
                ],
                'sticky': 'we' if is_hori else 'ns'}),
             ])
        style.configure(f'CustomScrollbarStyle.{v}.TScrollbar', troughcolor=troughcolor, background=background, arrowcolor=arrowcolor)
        # Comment in the following to customize disable/active colors, whatever that means
        # style.map(f'CustomScrollbarStyle.{v}.TScrollbar', background=[('pressed', '!disabled', disabledcolor), ('active', 'orange')])
    return "CustomScrollbarStyle.Horizontal.TScrollbar", "CustomScrollbarStyle.Vertical.TScrollbar"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM