Source code for ttkwidgets.font.chooser

"""
Author: RedFantom
License: GNU GPLv3
Source: This repository
"""
# Based on an idea by Nelson Brochado (https://www.github.com/nbro/tkinter-kit)
try:
    import Tkinter as tk
    import ttk
    import tkFont as font
except ImportError:
    import tkinter as tk
    from tkinter import ttk
    from tkinter import font
from .familylistbox import FontFamilyListbox
from .sizedropdown import FontSizeDropdown
from .propertiesframe import FontPropertiesFrame


[docs]class FontChooser(tk.Toplevel): """ A Toplevel to choose a :class:`~font.Font` from a list. Should only be used through :func:`askfont`. """
[docs] def __init__(self, master=None, **kwargs): """ Create a FontChooser. :param master: master window :type master: widget :param kwargs: keyword arguments passed to :class:`tk.Toplevel` initializer """ tk.Toplevel.__init__(self, master, **kwargs) self.wm_title("Choose a font") self.resizable(False, False) self.style = ttk.Style() self.style.configure("FontChooser.TLabel", font=("default", 11), relief=tk.SUNKEN, anchor=tk.CENTER) self._font_family_header = ttk.Label(self, text="Font family", style="FontChooser.TLabel") self._font_family_list = FontFamilyListbox(self, callback=self._on_family, height=8) self._font_label_variable = tk.StringVar() self._font_label = ttk.Label(self, textvariable=self._font_label_variable, background="white") self._font_properties_header = ttk.Label(self, text="Font properties", style="FontChooser.TLabel") self._font_properties_frame = FontPropertiesFrame(self, callback=self._on_properties, label=False) self._font_size_header = ttk.Label(self, text="Font size", style="FontChooser.TLabel") self._size_dropdown = FontSizeDropdown(self, callback=self._on_size, width=4) self._example_label = tk.Label(self, text="Example", anchor=tk.CENTER, background="white", height=2, relief=tk.SUNKEN) self._family = None self._size = 11 self._bold = False self._italic = False self._underline = False self._overstrike = False self._font = None self._ok_button = ttk.Button(self, text="OK", command=self._close) self._cancel_button = ttk.Button(self, text="Cancel", command=self._cancel) self._grid_widgets()
def _grid_widgets(self): """Puts all the child widgets in the correct position.""" self._font_family_header.grid(row=0, column=1, sticky="nswe", padx=5, pady=5) self._font_label.grid(row=1, column=1, sticky="nswe", padx=5, pady=(0, 5)) self._font_family_list.grid(row=2, rowspan=3, column=1, sticky="nswe", padx=5, pady=(0, 5)) self._font_properties_header.grid(row=0, column=2, sticky="nswe", padx=5, pady=5) self._font_properties_frame.grid(row=1, rowspan=2, column=2, sticky="we", padx=5, pady=5) self._font_size_header.grid(row=3, column=2, sticky="we", padx=5, pady=5) self._size_dropdown.grid(row=4, column=2, sticky="we", padx=5, pady=5) self._example_label.grid(row=5, column=1, columnspan=2, sticky="nswe", padx=5, pady=5) self._ok_button.grid(row=6, column=2, sticky="nswe", padx=5, pady=5) self._cancel_button.grid(row=6, column=1, sticky="nswe", padx=5, pady=5) def _on_family(self, family): """ Callback if family is changed :param family: family name """ self._font_label_variable.set(family) self._family = family self._on_change() def _on_size(self, size): """ Callback if size is changed :param size: int size """ self._size = size self._on_change() def _on_properties(self, properties): """ Callback if properties are changed. :param properties: (bool bold, bool italic, bool underline, bool overstrike) """ self._bold, self._italic, self._underline, self._overstrike = properties self._on_change() def _on_change(self): """Callback if any of the values are changed.""" font = self.__generate_font_tuple() self._example_label.configure(font=font) def __generate_font_tuple(self): """ Generate a font tuple for tkinter widgets based on the user's entries. :return: font tuple (family_name, size, *options) """ if not self._family: return None font = [self._family, self._size] if self._bold: font.append("bold") if self._italic: font.append("italic") if self._underline: font.append("underline") if self._overstrike: font.append("overstrike") return tuple(font) @property def font(self): """ Selected font. :return: font tuple (family_name, size, \*options), :class:`~font.Font` object """ if self._family is None: return None, None else: font_tuple = self.__generate_font_tuple() font_obj = font.Font(family=self._family, size=self._size, weight=font.BOLD if self._bold else font.NORMAL, slant=font.ITALIC if self._italic else font.ROMAN, underline=1 if self._underline else 0, overstrike=1 if self._overstrike else 0) return font_tuple, font_obj def _close(self): """Destroy the window.""" self.destroy() def _cancel(self): """Cancel font selection and destroy window.""" self._family = None self.destroy()
[docs]def askfont(): """ Opens a :class:`FontChooser` toplevel to allow the user to select a font :return: font tuple (family_name, size, \*options), :class:`~font.Font` object """ chooser = FontChooser() chooser.wait_window() return chooser.font