This code adds the following functionality to the basic tkinter.Tk()
class...
settings-file interaction for persistent application settings
fullscreen functionality using F11, can remember last configuration or be defaulted
removes the need for multiple
root.configure()
statementsremoves the need for
root.title()
androot.row/columnconfigure()
You adjust the default window by calling it using the Window() class, and then you can use two functions to adjust the settings file (which will be named settings.ini
by default).
root.set()
configures all of the software options found in settings.ini in realtime.root.get()
returns a dictionary with the settings you want to reference fromsettings.ini
- you can supply multiple arguments to both of these functions
One thing that always bugged me about tkinter was the need for multiple root.configure()
statements, so I wrote a function called root.config()
that loops through all the keyword arguments you supply and runs the appropriate configuration for them.
- this function also handles the
title()
androw/columnconfigure()
functions in this format:
root = Window()
root.config(bg='black', title='My Window', row=(0, 1), col=(0, 1))
root.mainloop()
This creates a basic window with a black background, a title ("My Window"), and row 0 and column 0 are set to weight = 1.
The code for this Window()
class is below, along with an example setup. You can simply copy/paste this into your editor and it'll run as a standalone.
import tkinter as tk
import os
class Window(tk.Tk):
def __init__(self, settings_file='./settings.ini'):
self.window = super()
self.window.__init__()
self.window.bind('<F11>', self.toggleFullscreen)
self.window.protocol('WM_DELETE_WINDOW', self.closing)
### the settings file is where your window properties are stored ###
self.file = settings_file
### checking if settings file exists ###
try:
open(self.file)
### if settings file doesn't exist, it gets created ###
except Exception as e:
print('settings file not found.\n'
'writing initial settings file.')
with open(self.file, 'w') as f:
initial_settings = [
### Create your default settings file file here ###
'; display settings\n\n',
'fullscreen=False\n',
'resolution=720x480\n',
'screenres=%dx%d\n' % (self.winfo_screenwidth(),
self.winfo_screenheight()),
'resizex=True\n',
'resizey=True\n\n'
'fontfamily=TkDefaultFont\n',
'fontsize=12'
]
for i in initial_settings:
f.write(i)
open(self.file, 'w')
###
### reading the settings file
with open(self.file) as f:
settings = f.readlines()
self.settings = settings
self.update()
### this refreshes the window size and properties ###
def update(self):
with open(self.file) as f:
settings = f.readlines()
self.settings = settings
self.font = (self.get('fontf')['fontfamily'],
self.get('fonts')['fontsize'])
self.window.resizable(self.get('rx')['resizex'],
self.get('ry')['resizey'])
self.window.geometry('%s' % self.get('res')['resolution'])
self.window.overrideredirect(0)
if self.get('fs')['fullscreen'] == 'True':
self.window.geometry('%s' % self.get('screenres')['screenres'])
self.toggleFullscreen(None)
self.window.update()
### this function changes the window to be fullscreen or normal ###
def toggleFullscreen(self, event=None):
if self.get('fullscreen')['fullscreen'] == 'True' and event:
self.set(fs = False)
self.window.overrideredirect(0)
return
if self.get('fullscreen')['fullscreen'] == 'False' and event:
if event: self.set(fs = True)
self.window.overrideredirect(1)
self.window.geometry('%sx%s+0+0'
% (self.winfo_screenwidth(),
self.winfo_screenheight()))
return
if not event:
if self.get('fullscreen')['fullscreen'] == 'True':
self.window.overrideredirect(1)
self.window.geometry('%sx%s+0+0'
% (self.winfo_screenwidth(),
self.winfo_screenheight()))
else:
self.window.overrideredirect(0)
self.window.update()
### last-minute cleanup before closing the window ###
def closing(self):
#self.set(fs=False)
self.window.destroy()
### set the values in settings file to keyword arguments ###
def set(self, **kwargs):
### shorthands for the set command ###
if 'fs' in kwargs: kwargs['fullscreen'] = kwargs.pop('fs')
if 'res' in kwargs: kwargs['resolution'] = kwargs.pop('res')
if 'rx' in kwargs: kwargs['resizex'] = kwargs.pop('rx')
if 'ry' in kwargs: kwargs['resizey'] = kwargs.pop('ry')
for i in kwargs:
for n, j in enumerate(self.settings):
if j.lower().startswith(i):
j = j.replace(
j [j.find('=')+1:],
str(kwargs[i]) + '\n'
)
self.settings[n] = j
with open(self.file, 'w') as f:
for i in self.settings:
f.write(i)
self.update()
### search through the settings and pull the values of each argument ###
def get(self, *args):
args = ['fullscreen' if i == 'fs' else i for i in args]
args = ['resolution' if i == 'res' else i for i in args]
args = ['resizex' if i == 'rx' else i for i in args]
args = ['resizey' if i == 'ry' else i for i in args]
args = ['fontfamily' if i == 'fontf' else i for i in args]
args = ['fontsize' if i == 'fonts' else i for i in args]
results = {}
### get the rest of the text following the = sign in settings file ###
for value in args:
for i, j in enumerate(self.settings):
if j.startswith(value):
results[value] = j[j.find('=')+1:].strip()
return results
### run a configure function for each keyword argument ###
def config(self, **kwargs):
### title the window ###
if 'title' in kwargs:
self.title = kwargs['title']
self.window.title(kwargs.pop('title'))
### row configure ###
if 'row' in kwargs:
self.window.rowconfigure(kwargs['row'][0],
weight = kwargs['row'][1])
kwargs.pop('row')
### column configure ###
if 'column' in kwargs or 'col' in kwargs:
try:
kwargs['column'] = kwargs.pop('col')
except: pass
self.window.columnconfigure(kwargs['column'][0],
weight = kwargs['column'][1])
kwargs.pop('column')
self.window.configure(**kwargs)
### the following is an example to show how this class is used ###
root = Window()
### creating a small, non-resizable root window that is windowed by default
root.set(fs=False, res='240x160',
rx=False, ry=False)
### basic styling and configuration with window title
root.config(bg='black',
bd=12,
relief=tk.SUNKEN,
title='Window')
### setting the default font size for the window
root.set(fontsize=32)
label = tk.Label(root, text='test', fg='white',
bg=root['bg'], font=root.font)
label.pack(fill = tk.BOTH, expand=True)
### You can toggle fullscreen by pressing F11
root.mainloop()
You can also add and change shorthands for the set()
and get()
methods using list comprehension, as shown in the source code.
Any feedback on this would be highly appreciated, as I know there are a few things I'd like to improve!
The code for implementing fullscreen is not very DRY, and I know there's probably a way around this.
To use the
get()
function, you have to specify the key you're looking to pull.
# example
print(root.get('fs')['fullscreen'])
I know this can probably be fixed by changing the output from a dictionary to a list, so I'll do that soon.
Either way, let me know what you think, or how I can improve this. I wanted to make this as a way of speeding up the rudimentary GUI creation process, and hopefully it can be used to get the ugly stuff out of the way faster.
Thanks in advance!