tkinter:如何将一个 class 中定义的自定义 ttk 样式名称应用到其他 classes

tkinter: How to apply customized ttk stylename that is defined in one class to other classes

我想将 class 中定义的自定义样式名称应用于其他 class 中的小部件。我该如何实施?

以下是供参考的测试脚本。我想将样式名称 'page.TFrame''press.TButton' 应用于 classes Page1Page2

测试脚本:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# tkinter modules
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkFont


class App(ttk.Frame):


    def __init__(self, parent=None, *args, **options):
        # Extract key and value from **options using Python3 "pop" function:
        #   pop(key[, default])
        self.style = options.pop('style',ttk.Style())
        self.bg0   = options.pop('background1','light grey')
        self.bg1   = options.pop('background2','grey')
        self.fg0   = options.pop('fg_link','black')
        self.fg1   = options.pop('fg_text','white')
        self.font  = options.pop('font',tkFont.Font(family='Nimbus Roman No9 L',
                                 size='10', weight='normal'))

        # Initialise App Frame
        ttk.Frame.__init__(self, parent, style='self.TFrame')
        self.__setFont()
        self.__setStyle()
        self.__createPages(parent)


    def __setFont(self):
        """Set the fonts to be used to build the App GUI."""
        self.fontTitle = self.font.copy()
        self.fontTitle.config(size='30')
        self.font.config(size='13')


    def __setStyle(self):
        """Customise ttk styles""" 
        ## LoginPanel styles
        self.style.configure('self.TFrame', background='pink')
        self.style.configure('page.TFrame', background=self.bg0)
        self.style.configure('press.TButton', font=self.fontTitle,
                             background=self.bg0, foreground=self.fg0,
                             relief='raised')


    def __createPages(self, parent):
        """Create Login and NewUser pages."""
        self._frames = {}
        for F in (Page1, Page2):
            page_name = F.__name__
            frame = F(parent=self)
            self._frames[page_name] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.showFrame("Page1")

        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)


    def showFrame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self._frames[page_name]
        frame.tkraise()



class Page1(ttk.Frame):

    def __init__(self, parent):
        ttk.Frame.__init__(self, parent, style='What to write here?')

        b1 = ttk.Button(self, text='Page 1',,
                        style='What to write here?')
        b1 .grid(row=0, column=0, sticky='nsew')

        b2 = ttk.Button(self, text='Goto Page 2?',
                        command=lambda: parent.showFrame("Page2"))
        b2 .grid(row=1, column=0, sticky='nsew')


class Page2(ttk.Frame):

    def __init__(self, parent):
        ttk.Frame.__init__(self, parent, style='What to write here?')

        b1 = ttk.Button(self, text='Page 2',
                        style='What to write here?')
        b1.grid(row=0, column=0, sticky='nsew')

        b2 = ttk.Button(self, text='Goto Page 1?',
                        command=lambda: parent.showFrame("Page1"))
        b2 .grid(row=1, column=0, sticky='nsew')


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('400x350+300+300')
    BG1 = 'blue'
    BG0 = 'lightblue'
    FG0 = 'white'
    FG1 = 'light blue'

    app = App(root, background1=BG0, background2=BG1,
                  fg_link=FG1, fg_text=FG0)
    app.grid(row=0, column=0, sticky='nsew')

    root.rowconfigure(0, weight=1)
    root.columnconfigure(0, weight=1)

    root.mainloop()

我终于想通了,令人惊讶的是答案很简单。

回答:我只需要将包含我要使用的自定义样式名称的样式属性参数传递给另一个需要使用这些样式的类名字。在我的脚本中,需要传递的属性参数是self.style。希望这个回答能帮到有同样需求的人。

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# tkinter modules
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.font as tkFont


class App(ttk.Frame):


    def __init__(self, parent=None, *args, **options):
        # Extract key and value from **options using Python3 "pop" function:
        #   pop(key[, default])
        self.style = options.pop('style',ttk.Style())
        self.bg0   = options.pop('background1','light grey')
        self.bg1   = options.pop('background2','grey')
        self.fg0   = options.pop('fg_link','black')
        self.fg1   = options.pop('fg_text','white')
        self.font  = options.pop('font',tkFont.Font(family='Nimbus Roman No9 L',
                                 size='10', weight='normal'))

        # Initialise App Frame
        ttk.Frame.__init__(self, parent, style='self.TFrame')
        self.__setFont()
        self.__setStyle()
        self.__createPages(parent)


    def __setFont(self):
        """Set the fonts to be used to build the App GUI."""
        self.fontTitle = self.font.copy()
        self.fontTitle.config(size='30')
        self.font.config(size='13')


    def __setStyle(self):
        """Customise ttk styles""" 
        ## LoginPanel styles
        self.style.configure('self.TFrame', background='pink')
        self.style.configure('page.TFrame', background=self.bg0)
        self.style.configure('press.TButton', font=self.fontTitle,
                             background=self.bg1, foreground=self.fg0,
                             relief='raised')


    def __createPages(self, parent):
        """Create Login and NewUser pages."""
        self._frames = {}
        for F in (Page1, Page2):
            page_name = F.__name__
            frame = F(parent=self, style=self.style) #pass style attribute
            self._frames[page_name] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.showFrame("Page1")

        parent.rowconfigure(0, weight=1)
        parent.columnconfigure(0, weight=1)


    def showFrame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self._frames[page_name]
        frame.tkraise()



class Page1(ttk.Frame):

    def __init__(self, parent, style): #added `style` argument
        ttk.Frame.__init__(self, parent, style='page.TFrame') #call the stylename

        b1 = ttk.Button(self, text='Page 1', style='press.TButton') #call the stylename
        b1 .grid(row=0, column=0, sticky='nsew')

        b2 = ttk.Button(self, text='Goto Page 2?',
                        command=lambda: parent.showFrame("Page2"))
        b2 .grid(row=1, column=0, sticky='nsew')


class Page2(ttk.Frame):

    def __init__(self, parent, style): #added `style` argument
        ttk.Frame.__init__(self, parent, style='page.TFrame') #call the stylename

        b1 = ttk.Button(self, text='Page 2', style='press.TButton') #call the stylename
        b1.grid(row=0, column=0, sticky='nsew')

        b2 = ttk.Button(self, text='Goto Page 1?',
                        command=lambda: parent.showFrame("Page1"))
        b2 .grid(row=1, column=0, sticky='nsew')


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('400x350+300+300')
    BG1 = 'blue'
    BG0 = 'lightblue'
    FG0 = 'white'
    FG1 = 'light blue'

    app = App(root, background1=BG0, background2=BG1,
                  fg_link=FG1, fg_text=FG0)
    app.grid(row=0, column=0, sticky='nsew')

    root.rowconfigure(0, weight=1)
    root.columnconfigure(0, weight=1)

    root.mainloop()