pythontkintertcltk-toolkitttkthemes

ttkthemes doesn't theme entire window when applied to root


None of the themes I've tried in ttkthemes will theme the entire window. I apply the theme to the root/self and it will only theme text/buttons

Screenshots:

Window

I was expecting the window to fill the entire way, is there something I'm missing?

Code:

class Window(ThemedTk):
    def __init__(self):
        ThemedTk.__init__(self)

        self.tk.call('lappend', 'auto_path', 'correct_path_to_theme')
        self.tk.call('package', 'require', 'awdark')
        s = ttk.Style()
        s.theme_use("awdark")

        # frame all content will sit inside of
        mainframe = ttk.Frame(self, width=self.width, height=self.height)
        mainframe.pack(side="top", fill="both", expand=True)


        self.frames = {}

        for F in (
            HomePage,
        ):
            frame = F(mainframe, self)


            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(HomePage)

    def show_frame(self, fr):
        frame = self.frames[fr]
        frame.tkraise()


# Home Page of the app
class HomePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)

        

        # header label
        header_label = ttk.Label(
            self, text="Post Visual Inspection Board Capture Program", justify="center"
        )
        header_label.pack()

        # will start the new capture process
        new_capture_buton = ttk.Button(
            self,
            text="New Capture",
            command=lambda: controller.show_frame(InstructionsPage),
        )

        new_capture_buton.place(relx=0.5, rely=0.5, anchor=tk.CENTER)

Solution

  • Toplevels (including the main window) are not themed widgets. They don't know anything about the theming system. They also have other significant powers that make simply repeating the code "but with theming" non-trivial.

    The simple fix (i.e., what I've always done) is to pack a themed frame inside the toplevel as the only direct child and to make it always cover the whole of its parent. Then put your other themed widgets inside that. It's technically not a themed toplevel, but it looks and works just like it was one (provided you use the right handle for working with it) so that's good enough.

    [EDIT]: Thinking about it a bit more, you could place the themed frame (first) inside the toplevel with absolute position 0,0 and relative width/height 1.0/1.0. Placed widgets don't participate in geometry calculations for their parent, so in this case that will mean that the themed frame just sits behind everything else. Exactly as wanted. The advantage of this is then you can largely forget about the themed background entirely; you pack or grid your widgets into the toplevel exactly as before.

    I always forget the placer. It's not commonly used, but sometimes it is exactly the thing you want.