Custom object display (repr)#
The default way of displaying objects is as follows: ClassName(param1=..., param2=..., param3=..., ...).
This printout / repr can b overridden with the use of tkclasswiz.convert.ObjectInfo.register_repr() method.
- classmethod ObjectInfo.register_repr(class_: type, repr: Callable[[ObjectInfo], str], inherited: bool = False)
Registers a custom __repr__ (string representation of object) function. The function must as a single parameter accept the
ObjectInfoinstance being represented as a string.- Parameters:
class (type) – The class for which this custom
repris being register.repr (Callable[[ObjectInfo], str]) – The function that will provide custom
__repr__. As a parameter it accepts theObjectInfoobject. It returns astr(string).inherited (bool) – Boolean flag. Setting it to True will register repr for inherited members as well. Defaults to False.
For example, let’s say I want to define some logical operators and want them to be displayed differently.
The example shows how a custom repr display can be made. It may look a bit much, but the only thing that matters
is the emphasized register_repr() method call.
Inside the call, a lambda function is provided. The lambda accepts
the ObjectInfo object and outputs a string.
That string is made up of the name of a logical operator and the operants in the following format:
<op1> <operator name> <op2> <operator name> <op3> .... If the operator’s name is or_op, it will be displayed
as <op1> or <op2> or <op3> .... If the operator’s name is and_op, it will be displayed as
<op1> and <op2> and <op3> ....
1from typing import List
2from abc import ABC, abstractmethod
3
4import tkinter as tk
5import tkinter.ttk as ttk
6import tkclasswiz as wiz
7
8class base_op(ABC):
9 @abstractmethod
10 def evaluate(self):
11 pass
12
13class bool_op(base_op):
14 def __init__(self, operants: List["base_op"]) -> None:
15 self.operants = operants
16
17class and_op(bool_op):
18 def evaluate(self):
19 return all(op.evaluate() for op in self.operants)
20
21class or_op(bool_op):
22 def evaluate(self):
23 return any(op.evaluate() for op in self.operants)
24
25class contains(base_op):
26 def __init__(self, op: str) -> None:
27 pass
28
29 def evaluate(self):
30 # For demonstration purposes. Otherwise, we would usually check if op is contained within string
31 return True
32
33class MyLogicResult:
34 def __init__(self, expression: base_op) -> None:
35 self.expression = expression
36
37
38wiz.ObjectInfo.register_repr(
39 bool_op,
40 lambda oi: "(" +
41 f' {oi.class_.__name__.removesuffix("_op")} '
42 .join(map(repr, oi.data["operants"])) +
43 ")",
44 True
45)
46
47# Tkinter main window
48root = tk.Tk("Test")
49
50# Modified tkinter Combobox that will store actual objects instead of strings
51combo = wiz.ComboBoxObjects(root)
52combo.pack(fill=tk.X, padx=5)
53
54def define(old = None):
55 """
56 Function for opening a window either in new definition mode (old = None) or
57 edit mode (old != None)
58 """
59 assert old is None or isinstance(old, wiz.ObjectInfo)
60 window = wiz.ObjectEditWindow()
61 window.open_object_edit_frame(MyLogicResult, combo)
62
63# Main GUI structure
64ttk.Button(text="Open", command=define).pack()
65root.mainloop()