10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Tkinter font wrapper 20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# written by Fredrik Lundh, February 1998 40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# FIXME: should add 'displayof' option where relevant (actual, families, 60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# measure, and metrics) 70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__version__ = "0.9" 100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 110a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport Tkinter 120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# weight/slant 140a8c90248264a8b26970b4473770bcc3df8515fJosh GaoNORMAL = "normal" 150a8c90248264a8b26970b4473770bcc3df8515fJosh GaoROMAN = "roman" 160a8c90248264a8b26970b4473770bcc3df8515fJosh GaoBOLD = "bold" 170a8c90248264a8b26970b4473770bcc3df8515fJosh GaoITALIC = "italic" 180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 190a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef nametofont(name): 200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """Given the name of a tk named font, returns a Font representation. 210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """ 220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return Font(name=name, exists=True) 230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 240a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass Font: 250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """Represents a named font. 270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Constructor options are: 290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao font -- font specifier (name, system font, or (family, size, style)-tuple) 310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao name -- name to use for this font configuration (defaults to a unique name) 320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao exists -- does a named font by this name already exist? 330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Creates a new named font if False, points to the existing font if True. 340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Raises _Tkinter.TclError if the assertion is false. 350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao the following are ignored if font is specified: 370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao family -- font 'family', e.g. Courier, Times, Helvetica 390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao size -- font size in points 400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao weight -- font thickness: NORMAL, BOLD 410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao slant -- font slant: ROMAN, ITALIC 420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao underline -- font underlining: false (0), true (1) 430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao overstrike -- font strikeout: false (0), true (1) 440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """ 460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _set(self, kw): 480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options = [] 490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k, v in kw.items(): 500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options.append("-"+k) 510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options.append(str(v)) 520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return tuple(options) 530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _get(self, args): 550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options = [] 560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for k in args: 570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options.append("-"+k) 580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return tuple(options) 590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def _mkdict(self, args): 610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options = {} 620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for i in range(0, len(args), 2): 630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options[args[i][1:]] = args[i+1] 640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return options 650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __init__(self, root=None, font=None, name=None, exists=False, **options): 670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not root: 680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root = Tkinter._default_root 690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if font: 700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # get actual settings corresponding to the given font 710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao font = root.tk.splitlist(root.tk.call("font", "actual", font)) 720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao font = self._set(options) 740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not name: 750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao name = "font" + str(id(self)) 760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.name = name 770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if exists: 790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.delete_font = False 800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # confirm font exists 810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.name not in root.tk.call("font", "names"): 820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise Tkinter._tkinter.TclError, "named font %s does not already exist" % (self.name,) 830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # if font config info supplied, apply it 840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if font: 850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root.tk.call("font", "configure", self.name, *font) 860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # create new font (raises TclError if the font exists) 880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root.tk.call("font", "create", self.name, *font) 890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.delete_font = True 900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # backlinks! 910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._root = root 920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._split = root.tk.splitlist 930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._call = root.tk.call 940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __str__(self): 960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.name 970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __eq__(self, other): 990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.name == other.name and isinstance(other, Font) 1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __getitem__(self, key): 1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self.cget(key) 1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __setitem__(self, key, value): 1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self.configure(**{key: value}) 1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def __del__(self): 1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao try: 1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if self.delete_font: 1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._call("font", "delete", self.name) 1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except (KeyboardInterrupt, SystemExit): 1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao raise 1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao except Exception: 1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao pass 1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def copy(self): 1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Return a distinct copy of the current font" 1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return Font(self._root, **self.actual()) 1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def actual(self, option=None): 1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Return actual font attributes" 1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if option: 1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._call("font", "actual", self.name, "-"+option) 1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._mkdict( 1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._split(self._call("font", "actual", self.name)) 1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def cget(self, option): 1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Get font attribute" 1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._call("font", "config", self.name, "-"+option) 1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def config(self, **options): 1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Modify font attributes" 1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if options: 1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._call("font", "config", self.name, 1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao *self._set(options)) 1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return self._mkdict( 1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._split(self._call("font", "config", self.name)) 1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao configure = config 1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def measure(self, text): 1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Return text width" 1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return int(self._call("font", "measure", self.name, text)) 1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao def metrics(self, *options): 1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao """Return font metrics. 1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao For best performance, create a dummy widget 1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao using this font before calling this method.""" 1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if options: 1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return int( 1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao self._call("font", "metrics", self.name, self._get(options)) 1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao ) 1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao else: 1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao res = self._split(self._call("font", "metrics", self.name)) 1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options = {} 1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao for i in range(0, len(res), 2): 1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao options[res[i][1:]] = int(res[i+1]) 1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return options 1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef families(root=None): 1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Get font families (as a tuple)" 1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not root: 1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root = Tkinter._default_root 1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return root.tk.splitlist(root.tk.call("font", "families")) 1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef names(root=None): 1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao "Get names of defined fonts (as a tuple)" 1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao if not root: 1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root = Tkinter._default_root 1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao return root.tk.splitlist(root.tk.call("font", "names")) 1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# -------------------------------------------------------------------- 1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# test stuff 1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == "__main__": 1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao root = Tkinter.Tk() 1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao # create a font 1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao f = Font(family="times", size=30, weight=NORMAL) 1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.actual() 1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.actual("family") 1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.actual("weight") 1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.config() 1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.cget("family") 1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.cget("weight") 1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print names() 1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.measure("hello"), f.metrics("linespace") 1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.metrics() 2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao f = Font(font=("Courier", 20, "bold")) 2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao print f.measure("hello"), f.metrics("linespace") 2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao w = Tkinter.Label(root, text="Hello, world", font=f) 2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao w.pack() 2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao w = Tkinter.Button(root, text="Quit!", command=root.destroy) 2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao w.pack() 2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fb = Font(font=w["font"]).copy() 2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao fb.config(weight=BOLD) 2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao w.config(font=fb) 2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao 2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao Tkinter.mainloop() 217