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.
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.