0
votes

I am new at tkinter, and somewhat new at python. I have an application where I need to know the parameters (font used: Arial, Calibri, etc..., size, color: foreground I believe in tkinter, effect: normal, bold, italic, etc..) of the default font TkDefaultFont used by my widgets. Today I don't even know what color (foreground in tkinter) to go back to after I change it, since I have no way to "read" the present parameter settings. I have an Entry widget and will validate the input. If the input is invalid, I will change the color (foreground) to red. The code below tells you what I have done, what I know and don't know. Any help will be very appreciated!

from tkinter import *
from tkinter import ttk
import tkinter.font as tkFont

def JMCheckButton2Command(*args):
    if JMCheckButton2Variable.get()==1:
        JMEntry.config(foreground = 'red')
    else:
        JMEntry.config(foreground = 'black')
    
#######################       Tk()      #######################
JMWindow = Tk()
s=ttk.Style()
print('\nTheme names are ', s.theme_names())
print('\nLayout of style TButton is:\n', s.layout('TButton'))
print('\nLayout of style TEntry is:\n', s.layout('TEntry'))
print("\nOptions available for element 'Button.label':\n", 
      s.element_options('Button.label'))
print("\nOptions available for element 'Entry.textarea':\n", 
      s.element_options('Entry.textarea'))
print("\nFont used in style 'TButton': ", s.lookup('TButton', 'font'))
print("\nFont used in style 'TButton': ", s.lookup('TEntry', 'font'))

#######################    ttk.Frame    #######################
JMFrame2=ttk.Frame(JMWindow, width='1i', height='2i', borderwidth='5',
                    relief='raised', padding=(5,5))
JMFrame2.grid()

#######################    ttk.Entry    #######################
JMEntryVariable = StringVar()
JMEntry = ttk.Entry(JMFrame2, textvariable=JMEntryVariable, width = 25)
JMEntry.insert(0, '100')   # insert new text at a given index

#######################    ttk.Label    #######################
JMLabel2Text2Display = StringVar()
JMLabel2Text2Display.set('Enter number: ')
JMLabel2 = ttk.Label(JMFrame2, textvariable = JMLabel2Text2Display, 
                     justify = 'center')

####################### ttk.Checkbutton #######################
JMCheckButton2Variable = IntVar()
JMCheckButton2=ttk.Checkbutton(JMFrame2, text='Change font color',
    command = JMCheckButton2Command, variable = JMCheckButton2Variable)

JMLabel2.grid(column=0, row=0)
JMEntry.grid(column=1, row=0)
JMCheckButton2.grid(column=2, row=0, sticky = 'w', padx=25)  

JMWindow.mainloop()
1
font = tkFont.nametofont('TkDefaultFont') and font.actual() will return the font attributes. But you need to call cget('foreground') on the widget to get the color.acw1668
Hi @acw1668 Your code did work and returned the info I wanted (I used font1 instead of font in my code): font1.actual() = {'family': 'Segoe UI', 'size': 9, 'weight': 'normal', 'slant': 'roman', 'underline': 0, 'overstrike': 0} I can now return to the original color and font by using JMEntry.config(foreground = '', font=('Segoe UI','9')).Jean-Marc

1 Answers

-1
votes

In general, Tk options/properties can be set @construction,
or later with calls to configure() / config().
What can be set with config(), can be queried with cget().
Can also index widgets with option names: widget['option']).

See tkinter sources, e.g. under: /usr/lib/python3.6/tkinter/
And Tcl/Tk documentation:
https://www.tcl.tk/man/tcl/TkCmd/contents.htm

For available options, you can search under:
https://www.tcl.tk/man/tcl/TkCmd/options.htm
and within:
/usr/lib/python3.6/tkinter/__init__.py

E.g. if you wanted to see options supported by class Button:
https://www.tcl.tk/man/tcl/TkCmd/button.htm
and within tkinter/__init__.py:

class Button(Widget):
    """Button widget."""
    def __init__(self, master=None, cnf={}, **kw):
        """Construct a button widget with the parent MASTER.

        STANDARD OPTIONS

            activebackground, activeforeground, anchor,
            ...
import tkinter as tk

root = tk.Tk()

l = tk.Label(
  root, text='asdf', font=('Times', 20)
)
l.pack()

tk.Button(
  text='query font',
  command=lambda: print(l.cget('font'))
).pack()

tk.Button(
  text='change font',
  command=lambda: l.configure(font=('Courier', 12))
).pack()

tk.Button(
  text='query foreground',
  command=lambda: print(l.cget('foreground'))
).pack()

tk.Button(
  text='change foreground',
  command=lambda: l.configure(foreground='#FF0000')
).pack()

root.mainloop()

Another example (different ways to get/set Tk options):
(See /usr/lib/python3.6/tkinter/font.py (has examples @end))

import tkinter as tk

from tkinter.font import Font  # Access Font class directly.
from tkinter import font  # To access 'weight' (BOLD etc.).

root = tk.Tk()

# printing f1 (without calling actual()) will print its name
f1 = Font(family='times', size=30, weight=font.NORMAL)
# printing f2 will print the tuple values
f2 = ('courier', 18, 'bold')  # Can also use plain tuples.

# This will inlcude name for f1 (created with Font class),
# but not for f2 (f2 is just a tuple).
print('Names of currently available fonts:')
for fName in font.names(): print(fName)

label = tk.Label(root, text='Label Text', font=f1)
label.pack()

tk.Button(
  text='Change font (config())',
  command=lambda: label.config(font=f1)
).pack()

# Note: cannot use assignment inside lambda,
# so using ordinary function as callback here.
def changeFontWithMapNotation(): label['font'] = f2
tk.Button(
  text='Change font (index map)',
  command=lambda: changeFontWithMapNotation()
).pack()

tk.Button(
  text='Read font (cget())',
  command=lambda: print('font:', label.cget('font'))
).pack()

tk.Button(
  text='Read font (index map)',
  command=lambda: print('font:', label['font'])
).pack()

root.mainloop()

After looking around a bit into ttk source:
/usr/lib/python3.6/tkinter/ttk.py
and at the official docs:
https://www.tcl.tk/man/tcl/TkCmd/ttk_intro.htm
https://www.tcl.tk/man/tcl/TkCmd/ttk_style.htm
here is a ttk example, creating & using a minimal custom style:

import tkinter as tk

from tkinter import ttk

root = tk.Tk()

styleDb = ttk.Style(root)

csName = 'CustomLabelStyle'

# Need to define layout for custom style, before using it.
# Just copy the corresponding layout from ttk.
csLayout = styleDb.layout('TLabel')
styleDb.layout(csName, csLayout)

# Set ttk options, for custom style, in ttk style database.
styleDb.configure(
  csName, 
  font=('Courier',18),
  foreground='#22AA55',
  background='#AA5522'
)

# Use custom style for specific widget.
label = ttk.Label(root, text='ttk label', style=csName)
label.pack()

ttk.Button(
  root, text='default style', 
  command=lambda: label.config(style='TLabel')
).pack()
ttk.Button(
  root, text='custom style', 
  command=lambda: label.config(style=csName)
).pack()

defaultLabelFont = styleDb.lookup('TLabel', 'font')
print(defaultLabelFont)
fontVar = tk.StringVar(root, styleDb.lookup(csName, 'font'))
ttk.Entry(root, textvariable=fontVar).pack()
ttk.Button(
  root,text='set custom style font',
  command=lambda: styleDb.configure(
    csName, font=fontVar.get()
  )
).pack()

root.mainloop()