Search code examples
pythontkinterttkttkwidgetstkinter-label

How do I to call a custom object with custom style methods and use it as a style for a label(and widgets in general) in tkinter?


So I am trying to import my own custom style methods into my main app to then use as a custom style in ttk.Label(), by calling the class method, but I'm having trouble finding a way to call it. Below is the example code of the main app.

import tkinter as tk
from tkinter import ttk
from custom_styles import customStyle

class MainApp:
    def __init__(self, master):
        self.master = master 
        **initialization code****
        
        #----style methods-----#
        self.styled = customStyle(self.master)
        

        #title label
        self.title_label = ttk.Label(self.master, text="test", style=self.styled.test())
        self.title_label.pack()
        
        

And below is the class I am calling the methods above from, which is different file.

from tkinter import ttk
import tkinter as tk

class customStyle:
    def __init__(self, master) -> None:
         self.master = master

    def test(self):
        style = ttk.Style()
        style.configure("test.TLabel",
                        foreground="white",
                        background="black",
                        padding=[10, 10, 10, 10])

I've tried to call just the name of the style method like this

self.title_label = ttk.Label(self.master, text="test", style='test.TLabel')

I've also tried to call the method by calling the class then method like this

self.title_label = ttk.Label(self.master, text="test", style=self.styled.test())

I knew this wouldn't work, but I still tried it

self.title_label = ttk.Label(self.master, text="test", style=self.styled.test('test.TLabel'))

I also tried not making an object out of the methods, so I took away the class and just made a list of functions, but that didn't work either. Of course, I looked on the internet and searched stack for questions, but to no avail. Maybe this structure I am trying to maintain is not efficient?

I'm honestly just looking to understand a way to call the methods w/o putting them in the same file, but I just don't know how to.


Solution

  • The style option requires the name of a style as a string. Since your function test returns None, it's the same as if you did ttk.Label(..., style=None)

    One solution is to have your test function return the style name:

    def test(self):
        ...
        return "test.TLabel"
    

    Of course, that means you can only use it for that one specific style. Another solution is that you leave it as-is and return nothing. In that case you can just hard-code the style. You must ensure that you call the test function, however, so that the style is initialized.

    self.styled.test()
    self.title_label = ttk.Label(self.master, text="test", style="test.TLabel")
    

    Arguably, a better option would be to add attributes to the class, and initialize the styles when you instantiate the class. It might look something like this:

    class customStyle:
        def __init__(self, master) -> None:
            self.master = master
            style = ttk.Style()
            style.configure("test.TLabel",...)
            ...
            self.label = "test.TLabel"
            self.button = "test.TButton"
            self.scrollbar = "test.TScrollbar"
            ...
    
    class MainApp:
        def __init__(self, master):
            self.master = master
            self.styled = customStyle(self.master)
    
            self.title_label = ttk.Label(..., style=self.styled.label)
            ...
    

    There are probably even better ways to do this. The point is, you need to pass a valid style name as a string to the style parameter of a ttk widget.