Search code examples
pythonpython-3.xtkinterttk

Frame bg color not being displayed in tkinter window


I'm trying to display a frame with color #231303 on a tkinter window. The contents of the frame(some progress bars) are being displayed, no problem, but the color of the frame is not being displayed. The link shows how the relevant part of the window looks. https://drive.google.com/file/d/1VHYW0t9UhjMUeNbwFijkrIy6RiToN0BN/view?usp=sharing As you can see, the frame color is not being displayed and it is not completely filling the width screen like I want it to either. There are no errors so I'm completely blank. I looked around for an explanation but could not find any. These are the relevant parts of my code '''

from tkinter import *
from tkinter.ttk import *

root = Tk()                            
root.title("Game") 
root.geometry("1280x720")
root["bg"] = "gray"
style = Style()

''' '''

def qn_func(self,qn_num,iteration) :
        Game.clear(self)
        global bar1,bar2,bar3,bar4
        style.configure("var.TFrame",bg="#231303")
        frame = Frame(root,height=120,width=1280,style="var.TFrame")
        frame.grid(row=0,column=0,sticky=W+E+N)

''' Here, bar1,bar2,bar3 and bar4 are the progress bars I display within the frame. I am actually very new to tkinter so please try to keep it simple. I also tried to display just the frame and its contents in a test file and this time, the color was displayed but the problem with the frame width still existed. Does anyone know why this is happening? It would be a great help if anyone could tell me why this is happening. I am also using tkinter.ttk in my code.


Solution

  • Maybe you would like to consider a more solid implementation of OOP.

    #don't pollute your namespace
    import tkinter as tk
    import tkinter.ttk as ttk
    from dataclasses import dataclass, asdict
    
    
    #create a "struct" to default to that represents ALL options for the widget
    @dataclass
    class Frame_dc:  
        background:  str = 'black'
        bordercolor: str = 'black' 
        darkcolor:   str = 'black'
        lightcolor:  str = 'black'
        relief:      str = 'flat'
        
    
    #prepare your data
    HeaderFrame = asdict(Frame_dc(*['#231303']*4)) #overwrite the first 4 vars with your custom color
    ErrorFrame  = asdict(Frame_dc(*['red']*4))
     
    
    #wrap all your styles in a custom theme 
    class CustomTheme(ttk.Style):
        def __init__(self, basetheme='clam'):
            ttk.Style.__init__(self)
            
            #slim example
            self.theme_create('custom', basetheme, {
                'custom.TFrame': {
                    'configure': HeaderFrame,
                },
                'error.TFrame': {
                    'configure': ErrorFrame,
                },
                #add more custom styles here
                #see: https://docs.python.org/3/library/tkinter.ttk.html#tkinter.ttk.Style.theme_create
            })
            self.theme_use('custom')
            
    
    #extend your root
    class App(tk.Tk):
        #define application constants
        WIDTH  = 1280
        HEIGHT = 720
        TITLE  = 'Game'
    
        def __init__(self, **kwargs):
            tk.Tk.__init__(self, **kwargs) #be more specific than "super()"
            CustomTheme()
            
            self.configure(bg="gray")
            
            #name things what they are
            self.header = ttk.Frame(self, height=120, style="custom.TFrame")
            self.header.grid(row=0, column=0, sticky='wen')
            
            #make `self.frame` fill width ~ 
            #technically this is making the entire column fill the width
            #but only because there is no other column with weight to disperse
            self.grid_columnconfigure(0, weight=1)
            
    
    #properly initialize your app
    if __name__ == '__main__':
        app = App()
        app.title(App.TITLE)
        app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
        app.mainloop()
    

    aside:

    Stay away from global. I can't think of a single language where global is a good thing, and I know a lot of languages. A good design pattern implements encapsulation. global is the antithesis of encapsulation. global could also be considered a forced dependency, depending on the context. Then you have the whole problem that: if I was going to hack your game you just left all the guts wide open for me to play with. If you have a good design you could possibly never use global for the entire rest of your life, without making a single sacrifice in functionality and access.