pytermgui.widgets.pixel_matrix
The module containing all the widgets that can be used to display pixel-based data.
View Source
0""" 1The module containing all the widgets that can be used to display 2pixel-based data. 3""" 4 5from __future__ import annotations 6 7from .base import Widget 8from ..parser import markup 9from ..regex import real_length 10from ..ansi_interface import MouseEvent, MouseAction 11 12__all__ = [ 13 "PixelMatrix", 14 "DensePixelMatrix", 15] 16 17 18class PixelMatrix(Widget): 19 """A matrix of pixels. 20 21 The way this object should be used is by accessing & modifying 22 the underlying matrix. This can be done using the set & getitem 23 syntacies: 24 25 ```python3 26 from pytermgui import PixelMatrix 27 28 matrix = PixelMatrix(10, 10, default="white") 29 for y in matrix.rows: 30 for x in matrix.columns: 31 matrix[y, x] = "black" 32 ``` 33 34 The above snippet draws a black diagonal going from the top left 35 to bottom right. 36 37 Each item of the rows should be a single PyTermGUI-parsable color 38 string. For more information about this, see 39 `pytermgui.ansi_interface.Color`. 40 """ 41 42 selected_pixel: tuple[tuple[int, int], str] | None 43 """A tuple of the position & value (color) of the currently hovered pixel.""" 44 45 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 46 """Initializes a PixelMatrix. 47 48 Args: 49 width: The amount of columns the matrix will have. 50 height: The amount of rows the matrix will have. 51 default: The default color to use to initialize the matrix with. 52 """ 53 54 super().__init__(**attrs) 55 56 self.rows = height 57 self.columns = width 58 59 self._matrix = [] 60 61 for _ in range(self.rows): 62 self._matrix.append([default] * self.columns) 63 64 self.selected_pixel = None 65 self.build() 66 67 @classmethod 68 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 69 """Creates a PixelMatrix from the given matrix. 70 71 The given matrix should be a list of rows, each containing a number 72 of cells. It is optimal for all rows to share the same amount of cells. 73 74 Args: 75 matrix: The matrix to use. This is a list of lists of strings 76 with each element representing a PyTermGUI-parseable color. 77 78 Returns: 79 A new type(self). 80 """ 81 82 obj = cls(max(len(row) for row in matrix), len(matrix)) 83 setattr(obj, "_matrix", matrix) 84 obj.build() 85 86 return obj 87 88 def _update_dimensions(self, lines: list[str]): 89 """Updates the dimensions of this matrix. 90 91 Args: 92 lines: A list of lines that the calculations will be based upon. 93 """ 94 95 self.static_width = max(real_length(line) for line in lines) 96 self.height = len(lines) 97 98 def handle_mouse(self, event: MouseEvent) -> bool: 99 """Handles a mouse event. 100 101 On hover, the `selected_pixel` attribute is set to the current pixel. 102 """ 103 104 if event.action is MouseAction.HOVER: 105 xoffset = event.position[0] - self.pos[0] 106 yoffset = event.position[1] - self.pos[1] 107 108 color = self._matrix[yoffset][xoffset // 2] 109 110 self.selected_pixel = ((xoffset // 2, yoffset), color) 111 return True 112 113 return False 114 115 def get_lines(self) -> list[str]: 116 """Returns lines built by the `build` method.""" 117 118 return self._lines 119 120 def build(self) -> list[str]: 121 """Builds the image pixels. 122 123 Returns: 124 The lines that this object will return, until a subsequent `build` call. 125 These lines are stored in the `self._lines` variable. 126 """ 127 128 lines: list[str] = [] 129 for row in self._matrix: 130 line = "" 131 for pixel in row: 132 if len(pixel) > 0: 133 line += f"[@{pixel}] " 134 else: 135 line += "[/] " 136 137 lines.append(markup.parse(line)) 138 139 self._lines = lines 140 self._update_dimensions(lines) 141 142 return lines 143 144 def __getitem__(self, indices: tuple[int, int]) -> str: 145 """Gets a matrix item.""" 146 147 posy, posx = indices 148 return self._matrix[posy][posx] 149 150 def __setitem__(self, indices: tuple[int, int], value: str) -> None: 151 """Sets a matrix item.""" 152 153 posy, posx = indices 154 self._matrix[posy][posx] = value 155 156 157class DensePixelMatrix(PixelMatrix): 158 """A more dense (2x) PixelMatrix. 159 160 Due to each pixel only occupying 1/2 characters in height, accurately 161 determining selected_pixel is impossible, thus the functionality does 162 not exist here. 163 """ 164 165 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 166 """Initializes DensePixelMatrix. 167 168 Args: 169 width: The width of the matrix. 170 height: The height of the matrix. 171 default: The default color to use to initialize the matrix with. 172 """ 173 174 super().__init__(width, height, default, **attrs) 175 176 self.width = width // 2 177 178 def handle_mouse(self, event: MouseEvent) -> bool: 179 """As mentioned in the class documentation, mouse handling is disabled here.""" 180 181 return False 182 183 def build(self) -> list[str]: 184 """Builds the image pixels, using half-block characters. 185 186 Returns: 187 The lines that this object will return, until a subsequent `build` call. 188 These lines are stored in the `self._lines` variable. 189 """ 190 191 lines = [] 192 lines_to_zip: list[list[str]] = [] 193 for row in self._matrix: 194 lines_to_zip.append(row) 195 if len(lines_to_zip) != 2: 196 continue 197 198 line = "" 199 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 200 for bottom, top in zip(bottom_row, top_row): 201 if len(top) + len(bottom) == 0: 202 line += " " 203 continue 204 205 if bottom == "": 206 line += markup.parse(f"[{top}]▀") 207 continue 208 209 markup_str = "@" + top + " " if len(top) > 0 else "" 210 211 markup_str += bottom 212 line += markup.parse(f"[{markup_str}]▄") 213 214 lines.append(line) 215 lines_to_zip = [] 216 217 self._lines = lines 218 self._update_dimensions(lines) 219 220 return lines
View Source
19class PixelMatrix(Widget): 20 """A matrix of pixels. 21 22 The way this object should be used is by accessing & modifying 23 the underlying matrix. This can be done using the set & getitem 24 syntacies: 25 26 ```python3 27 from pytermgui import PixelMatrix 28 29 matrix = PixelMatrix(10, 10, default="white") 30 for y in matrix.rows: 31 for x in matrix.columns: 32 matrix[y, x] = "black" 33 ``` 34 35 The above snippet draws a black diagonal going from the top left 36 to bottom right. 37 38 Each item of the rows should be a single PyTermGUI-parsable color 39 string. For more information about this, see 40 `pytermgui.ansi_interface.Color`. 41 """ 42 43 selected_pixel: tuple[tuple[int, int], str] | None 44 """A tuple of the position & value (color) of the currently hovered pixel.""" 45 46 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 47 """Initializes a PixelMatrix. 48 49 Args: 50 width: The amount of columns the matrix will have. 51 height: The amount of rows the matrix will have. 52 default: The default color to use to initialize the matrix with. 53 """ 54 55 super().__init__(**attrs) 56 57 self.rows = height 58 self.columns = width 59 60 self._matrix = [] 61 62 for _ in range(self.rows): 63 self._matrix.append([default] * self.columns) 64 65 self.selected_pixel = None 66 self.build() 67 68 @classmethod 69 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 70 """Creates a PixelMatrix from the given matrix. 71 72 The given matrix should be a list of rows, each containing a number 73 of cells. It is optimal for all rows to share the same amount of cells. 74 75 Args: 76 matrix: The matrix to use. This is a list of lists of strings 77 with each element representing a PyTermGUI-parseable color. 78 79 Returns: 80 A new type(self). 81 """ 82 83 obj = cls(max(len(row) for row in matrix), len(matrix)) 84 setattr(obj, "_matrix", matrix) 85 obj.build() 86 87 return obj 88 89 def _update_dimensions(self, lines: list[str]): 90 """Updates the dimensions of this matrix. 91 92 Args: 93 lines: A list of lines that the calculations will be based upon. 94 """ 95 96 self.static_width = max(real_length(line) for line in lines) 97 self.height = len(lines) 98 99 def handle_mouse(self, event: MouseEvent) -> bool: 100 """Handles a mouse event. 101 102 On hover, the `selected_pixel` attribute is set to the current pixel. 103 """ 104 105 if event.action is MouseAction.HOVER: 106 xoffset = event.position[0] - self.pos[0] 107 yoffset = event.position[1] - self.pos[1] 108 109 color = self._matrix[yoffset][xoffset // 2] 110 111 self.selected_pixel = ((xoffset // 2, yoffset), color) 112 return True 113 114 return False 115 116 def get_lines(self) -> list[str]: 117 """Returns lines built by the `build` method.""" 118 119 return self._lines 120 121 def build(self) -> list[str]: 122 """Builds the image pixels. 123 124 Returns: 125 The lines that this object will return, until a subsequent `build` call. 126 These lines are stored in the `self._lines` variable. 127 """ 128 129 lines: list[str] = [] 130 for row in self._matrix: 131 line = "" 132 for pixel in row: 133 if len(pixel) > 0: 134 line += f"[@{pixel}] " 135 else: 136 line += "[/] " 137 138 lines.append(markup.parse(line)) 139 140 self._lines = lines 141 self._update_dimensions(lines) 142 143 return lines 144 145 def __getitem__(self, indices: tuple[int, int]) -> str: 146 """Gets a matrix item.""" 147 148 posy, posx = indices 149 return self._matrix[posy][posx] 150 151 def __setitem__(self, indices: tuple[int, int], value: str) -> None: 152 """Sets a matrix item.""" 153 154 posy, posx = indices 155 self._matrix[posy][posx] = value
A matrix of pixels.
The way this object should be used is by accessing & modifying the underlying matrix. This can be done using the set & getitem syntacies:
from pytermgui import PixelMatrix
matrix = PixelMatrix(10, 10, default="white")
for y in matrix.rows:
for x in matrix.columns:
matrix[y, x] = "black"
The above snippet draws a black diagonal going from the top left to bottom right.
Each item of the rows should be a single PyTermGUI-parsable color
string. For more information about this, see
pytermgui.ansi_interface.Color
.
View Source
46 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 47 """Initializes a PixelMatrix. 48 49 Args: 50 width: The amount of columns the matrix will have. 51 height: The amount of rows the matrix will have. 52 default: The default color to use to initialize the matrix with. 53 """ 54 55 super().__init__(**attrs) 56 57 self.rows = height 58 self.columns = width 59 60 self._matrix = [] 61 62 for _ in range(self.rows): 63 self._matrix.append([default] * self.columns) 64 65 self.selected_pixel = None 66 self.build()
Initializes a PixelMatrix.
Args
- width: The amount of columns the matrix will have.
- height: The amount of rows the matrix will have.
- default: The default color to use to initialize the matrix with.
A tuple of the position & value (color) of the currently hovered pixel.
View Source
68 @classmethod 69 def from_matrix(cls, matrix: list[list[str]]) -> PixelMatrix: 70 """Creates a PixelMatrix from the given matrix. 71 72 The given matrix should be a list of rows, each containing a number 73 of cells. It is optimal for all rows to share the same amount of cells. 74 75 Args: 76 matrix: The matrix to use. This is a list of lists of strings 77 with each element representing a PyTermGUI-parseable color. 78 79 Returns: 80 A new type(self). 81 """ 82 83 obj = cls(max(len(row) for row in matrix), len(matrix)) 84 setattr(obj, "_matrix", matrix) 85 obj.build() 86 87 return obj
Creates a PixelMatrix from the given matrix.
The given matrix should be a list of rows, each containing a number of cells. It is optimal for all rows to share the same amount of cells.
Args
- matrix: The matrix to use. This is a list of lists of strings with each element representing a PyTermGUI-parseable color.
Returns
A new type(self).
View Source
99 def handle_mouse(self, event: MouseEvent) -> bool: 100 """Handles a mouse event. 101 102 On hover, the `selected_pixel` attribute is set to the current pixel. 103 """ 104 105 if event.action is MouseAction.HOVER: 106 xoffset = event.position[0] - self.pos[0] 107 yoffset = event.position[1] - self.pos[1] 108 109 color = self._matrix[yoffset][xoffset // 2] 110 111 self.selected_pixel = ((xoffset // 2, yoffset), color) 112 return True 113 114 return False
Handles a mouse event.
On hover, the selected_pixel
attribute is set to the current pixel.
View Source
Returns lines built by the build
method.
View Source
121 def build(self) -> list[str]: 122 """Builds the image pixels. 123 124 Returns: 125 The lines that this object will return, until a subsequent `build` call. 126 These lines are stored in the `self._lines` variable. 127 """ 128 129 lines: list[str] = [] 130 for row in self._matrix: 131 line = "" 132 for pixel in row: 133 if len(pixel) > 0: 134 line += f"[@{pixel}] " 135 else: 136 line += "[/] " 137 138 lines.append(markup.parse(line)) 139 140 self._lines = lines 141 self._update_dimensions(lines) 142 143 return lines
Builds the image pixels.
Returns
The lines that this object will return, until a subsequent
build
call. These lines are stored in theself._lines
variable.
Inherited Members
- pytermgui.widgets.base.Widget
- set_style
- set_char
- styles
- chars
- keys
- serialized
- is_bindable
- size_policy
- parent_align
- from_data
- bindings
- id
- selectables_length
- selectables
- is_selectable
- static_width
- relative_width
- terminal
- get_change
- contains
- handle_key
- serialize
- copy
- bind
- unbind
- execute_binding
- select
- debug
View Source
158class DensePixelMatrix(PixelMatrix): 159 """A more dense (2x) PixelMatrix. 160 161 Due to each pixel only occupying 1/2 characters in height, accurately 162 determining selected_pixel is impossible, thus the functionality does 163 not exist here. 164 """ 165 166 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 167 """Initializes DensePixelMatrix. 168 169 Args: 170 width: The width of the matrix. 171 height: The height of the matrix. 172 default: The default color to use to initialize the matrix with. 173 """ 174 175 super().__init__(width, height, default, **attrs) 176 177 self.width = width // 2 178 179 def handle_mouse(self, event: MouseEvent) -> bool: 180 """As mentioned in the class documentation, mouse handling is disabled here.""" 181 182 return False 183 184 def build(self) -> list[str]: 185 """Builds the image pixels, using half-block characters. 186 187 Returns: 188 The lines that this object will return, until a subsequent `build` call. 189 These lines are stored in the `self._lines` variable. 190 """ 191 192 lines = [] 193 lines_to_zip: list[list[str]] = [] 194 for row in self._matrix: 195 lines_to_zip.append(row) 196 if len(lines_to_zip) != 2: 197 continue 198 199 line = "" 200 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 201 for bottom, top in zip(bottom_row, top_row): 202 if len(top) + len(bottom) == 0: 203 line += " " 204 continue 205 206 if bottom == "": 207 line += markup.parse(f"[{top}]▀") 208 continue 209 210 markup_str = "@" + top + " " if len(top) > 0 else "" 211 212 markup_str += bottom 213 line += markup.parse(f"[{markup_str}]▄") 214 215 lines.append(line) 216 lines_to_zip = [] 217 218 self._lines = lines 219 self._update_dimensions(lines) 220 221 return lines
A more dense (2x) PixelMatrix.
Due to each pixel only occupying 1/2 characters in height, accurately determining selected_pixel is impossible, thus the functionality does not exist here.
View Source
166 def __init__(self, width: int, height: int, default: str = "", **attrs) -> None: 167 """Initializes DensePixelMatrix. 168 169 Args: 170 width: The width of the matrix. 171 height: The height of the matrix. 172 default: The default color to use to initialize the matrix with. 173 """ 174 175 super().__init__(width, height, default, **attrs) 176 177 self.width = width // 2
Initializes DensePixelMatrix.
Args
- width: The width of the matrix.
- height: The height of the matrix.
- default: The default color to use to initialize the matrix with.
View Source
As mentioned in the class documentation, mouse handling is disabled here.
View Source
184 def build(self) -> list[str]: 185 """Builds the image pixels, using half-block characters. 186 187 Returns: 188 The lines that this object will return, until a subsequent `build` call. 189 These lines are stored in the `self._lines` variable. 190 """ 191 192 lines = [] 193 lines_to_zip: list[list[str]] = [] 194 for row in self._matrix: 195 lines_to_zip.append(row) 196 if len(lines_to_zip) != 2: 197 continue 198 199 line = "" 200 top_row, bottom_row = lines_to_zip[0], lines_to_zip[1] 201 for bottom, top in zip(bottom_row, top_row): 202 if len(top) + len(bottom) == 0: 203 line += " " 204 continue 205 206 if bottom == "": 207 line += markup.parse(f"[{top}]▀") 208 continue 209 210 markup_str = "@" + top + " " if len(top) > 0 else "" 211 212 markup_str += bottom 213 line += markup.parse(f"[{markup_str}]▄") 214 215 lines.append(line) 216 lines_to_zip = [] 217 218 self._lines = lines 219 self._update_dimensions(lines) 220 221 return lines
Builds the image pixels, using half-block characters.
Returns
The lines that this object will return, until a subsequent
build
call. These lines are stored in theself._lines
variable.
Inherited Members
- pytermgui.widgets.base.Widget
- set_style
- set_char
- styles
- chars
- keys
- serialized
- is_bindable
- size_policy
- parent_align
- from_data
- bindings
- id
- selectables_length
- selectables
- is_selectable
- static_width
- relative_width
- terminal
- get_change
- contains
- handle_key
- serialize
- copy
- bind
- unbind
- execute_binding
- select
- debug