Within CircuitPython's displayio
library, a display group is a list of label or graphic attributes that are defined for each object of the display. This section of the Thermal Camera's primary process module defines the image_group
display group that the camera will use to show measured values, the sensor image or histogram, status message, and the histogram legend.
The camera's display group, image_group
, consists of 77 layered objects that start with a black screen-sized background in the back-most position. The next 64 objects of the display make up the colored blocks used for the image area.
The status message label comes next, followed by the values and labels in the display sidebar area. Finally, objects that make up the histogram legend top off the stack of display objects in image_group
.
The objects and their attributes are appended to the image_group
list one-at-a-time when first defined. When appended to image_group
, the attributes of each object are defined. For example, the alarm label alm is defined as a Label object with attributes that include the label's font, text contents, and text color:
alarm_label = Label(font, text="alm", color=WHITE)
The x/y position on the PyGamer's display screen is an attribute of the label object. Keeping with the grid block positioning scheme, the element_grid()
helper is used to convert the block column/row position to the x/y coordinates of the board's display screen. In this case, element_grid()
returns an x/y tuple for the intersection of column -1.8 and row 1.5:
pos = element_grid(-1.8, 1.5
)
The alarm label's display screen x/y coordinate attributes are set using the x/y tuple, pos
:
alarm_label.x = pos.x
alarm_label.y = pos.y
After defining the display object's attributes, it is appended to the image_group
display group:
image_group.append(alarm_label)
This process is repeated, starting from the back of the display and progressing towards the front, as each new object is appended to the display group.
Let's look at how all of the display objects are defined for the Thermal Camera.
Define Image Group and Create the Background Layer
The image_group
list needs to be defined before we can append any display group objects. The max_size
argument is set to the number of objects that will be used. In this case, we'll need 77 objects (image_group[0:76]
).
Now that the display group is ready, we'll define the background bitmap object and its attributes. The bitmap's size is the same as the display's width and height; color is black. The bitmap will be placed at x/y coordinate 0,0 (the upper left corner of the display). After it's defined, the background object is appended as the first object in the image_group
list.
### Define the display group ### image_group = displayio.Group() # Create a background color fill layer; image_group[0] color_bitmap = displayio.Bitmap(WIDTH, HEIGHT, 1) color_palette = displayio.Palette(1) color_palette[0] = BLACK background = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0) image_group.append(background)
Define the Thermal Image Display Group Layers
Next, the 64 squares used to represent sensor array temperatures will be defined and appended. Two for
loops are used to step through each column and row of squares. Each square is defined as a rectangle with width and height equal to ELEMENT_SIZE
. No color attribute is defined for the square, making it transparent -- for now.
# Define the foundational thermal image element layers; image_group[1:64] # image_group[#]=(row * 8) + column for row in range(0, 8): for col in range(0, 8): pos_x, pos_y = element_grid(col, row) element = Rect(x=pos_x, y=pos_y, width=ELEMENT_SIZE, height=ELEMENT_SIZE, fill=None, outline=None, stroke=0) image_group.append(element)
Define the Text Label Display Group Layers
Finally, the remaining text objects that display legends and values are defined and appended to the image_group
display group.
For each object, the label name is defined along with the font, text contents, font color, and the maximum number of characters to display. Next, the object's position attribute is defined using the element_grid()
helper to calculate the hardware-specific x/y display coordinates. After the attributes are defined, each object is appended to image_group
.
# Define labels and values using element grid coordinates status_label = Label(font, text="", color=BLACK) pos_x, pos_y = element_grid(2.5, 4) status_label.x = pos_x status_label.y = pos_y image_group.append(status_label) # image_group[65] alarm_label = Label(font, text="alm", color=WHITE) pos_x, pos_y = element_grid(-1.8, 1.5) alarm_label.x = pos_x alarm_label.y = pos_y image_group.append(alarm_label) # image_group[66] max_label = Label(font, text="max", color=RED) pos_x, pos_y = element_grid(-1.8, 3.5) max_label.x = pos_x max_label.y = pos_y image_group.append(max_label) # image_group[67] min_label = Label(font, text="min", color=CYAN) pos_x, pos_y = element_grid(-1.8, 7.5) min_label.x = pos_x min_label.y = pos_y image_group.append(min_label) # image_group[68] ave_label = Label(font, text="ave", color=YELLOW) pos_x, pos_y = element_grid(-1.8, 5.5) ave_label.x = pos_x ave_label.y = pos_y image_group.append(ave_label) # image_group[69] alarm_value = Label(font, text=str(ALARM_F), color=WHITE) pos_x, pos_y = element_grid(-1.8, 0.5) alarm_value.x = pos_x alarm_value.y = pos_y image_group.append(alarm_value) # image_group[70] max_value = Label(font, text=str(MAX_RANGE_F), color=RED) pos_x, pos_y = element_grid(-1.8, 2.5) max_value.x = pos_x max_value.y = pos_y image_group.append(max_value) # image_group[71] min_value = Label(font, text=str(MIN_RANGE_F), color=CYAN) pos_x, pos_y = element_grid(-1.8, 6.5) min_value.x = pos_x min_value.y = pos_y image_group.append(min_value) # image_group[72] ave_value = Label(font, text="---", color=YELLOW) pos_x, pos_y = element_grid(-1.8, 4.5) ave_value.x = pos_x ave_value.y = pos_y image_group.append(ave_value) # image_group[73] min_histo = Label(font, text="", color=CYAN) pos_x, pos_y = element_grid(0.5, 7.5) min_histo.x = pos_x min_histo.y = pos_y image_group.append(min_histo) # image_group[74] max_histo = Label(font, text="", color=RED) pos_x, pos_y = element_grid(6.5, 7.5) max_histo.x = pos_x max_histo.y = pos_y image_group.append(max_histo) # image_group[75] range_histo = Label(font, text="", color=BLUE) pos_x, pos_y = element_grid(2.5, 7.5) range_histo.x = pos_x range_histo.y = pos_y image_group.append(range_histo) # image_group[76]
Fun Facts about Display Group Objects
Objects and their attributes in the display group can be accessed in two ways. The most commonly-used method is to assign a name attribute to the object. For example, the text of the status message label can be set to display the text WELCOME in this manner:
status_label.text = "WELCOME"
Objects in image_group
can also be accessed by their indexed position in the display group. An index of 0 is the back-most object in the display group; the highest index value is front-most. The status message text can also be changed using the index:
image_group[65].text = "WELCOME"
The Thermal Camera uses both techniques. Named display objects are used whenever possible to clearly identify which object is being changed. For efficiency, however, the index position method is used when stepping through a sequence of image_group
objects, as when displaying the 64 colored blocks for the sensor image. The index position method is also used by the setup_mode()
helper when moving on-screen to select the alarm, maximum, or minimum parameter.
Text editor powered by tinymce.