There are a lot of things to consider about your code, and I will address all of them.
- You are importing all of
tkinter without any alias
- Calling your
root "doc1" implies that you think you will be making a "doc2", "doc3", etc.. out of that class, and that is not going to work. You can't have many root instances. At best, that should be Toplevel, but only if you intend to open a new window for every new document.
- You shouldn't be calling
mainloop inside the class, at all. You should be using module conventions. This way, you can import elements of this script into another script without worrying about this script running things automatically. At the very least, creating a wrapper for mainloop is silly. You can already call mainloop, what is the purpose of sticking it inside another method? (doc1.root.mainloop())
- Creating a method to do very specific grid placement isn't reusable. I would argue that a
mixin that makes certain features more usable, but keeps them dynamic would be a better approach. It isn't necessary to create a custom wrapper for widgets, but if you are going to put a gridding method on everything then why not make a better gridding method and have it automatically "mixed in" to everything that applies? And as long as you go that far you might as well include some other conveniences, as well.
- Something like
Document (ie, something where you may need many or may change often) likely shouldn't be the root. It should be IN the root. It certainly shouldn't have the root buried in it as a property.
Below gives numerous examples of the things I stated above. Those examples can and should be embellished. For instance, BaseWidget could include properties for x, rootx, y, rooty etc... The way ParentWidget is designed, you can use a range as the first argument of rowcfg and colcfg to do "mass configuring" in one call. They both return self so, they can be used inline.
import tkinter as tk
from typing import Iterable
class BaseWidget:
@property
def width(self) -> int:
self.update_idletasks()
return self.winfo_width()
@property
def height(self) -> int:
self.update_idletasks()
return self.winfo_height()
def grid_(self, r=None, c=None, rs=1, cs=1, s='nswe', **kwargs):
#this allows keyword shorthand, as well as original keywords
#while also allowing you to rearrange the above arguments
#so you know the exact order they appear and don't have to use the keyword, at all
self.grid(**{'row':r, 'column':c, 'rowspan':rs, 'columnspan':cs, 'sticky':s, **kwargs})
#return self so this can be used inline
return self
class ParentWidget:
@property
def descendants(self):
return self.winfo_children()
#inline and ranged grid_rowconfigure
def rowcfg(self, index, **options):
index = index if isinstance(index, Iterable) else [index]
for i in index:
self.grid_rowconfigure(i, **options)
#so this can be used inline
return self
#inline and ranged grid_columnconfigure
def colcfg(self, index, **options):
index = index if isinstance(index, Iterable) else [index]
for i in index:
self.grid_columnconfigure(i, **options)
#so this can be used inline
return self
class Custom_Label(tk.Label, BaseWidget):
@property
def text(self) -> str:
return self['text']
@text.setter
def text(self, value:str):
self['text'] = value
def __init__(self, master, **kwargs):
tk.Label.__init__(self, master, **kwargs)
class Document(tk.Frame, ParentWidget, BaseWidget):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
#the rest of this class is an example based on what little code you posted
#the results are not meant to be ideal. It's a demo of usage ... a gist
self.file_name = Custom_Label(self, text='File Name').grid_(1,2)
self.doc_title = Custom_Label(self, text='Document Title').grid_(2,2)
#possible
#r = range(len(self.descendants))
#self.colcfg(r, weight=1).rowcfg(r, weight=1)
self.colcfg(2, weight=1).rowcfg([1,2], weight=1)
class Root(tk.Tk, ParentWidget):
def __init__(self, title, width, height, x, y, **kwargs):
tk.Tk.__init__(self)
self.configure(**kwargs)
self.title(title)
self.geometry(f'{width}x{height}+{x}+{y}')
self.rowcfg(0, weight=1).colcfg(0, weight=1)
doc1 = Document(self).grid_()
if __name__ == '__main__':
Root('MyApplication', 800, 600, 200, 200, bg='#000000').mainloop()