Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

displayio.Group .hidden flag is not honored if set to True before content is appended to group. #4193

Closed
kmatch98 opened this issue Feb 12, 2021 · 3 comments · Fixed by #4915

Comments

@kmatch98
Copy link
Collaborator

I observed a strange behavior when using the .hidden flag of the displayio.Group where the group is actually visible, even when group.hidden is set to True.

If the group.hidden is set to True before content is appended into it, the .hidden flag is ignored.
The group.hidden flag's proper behavior can only be recovered if it set to False and then back to True again.

Here's the example code to replicate the issue. This was tested on the PyPortal.

CircuitPython version info: Adafruit CircuitPython 6.1.0 on 2021-01-21; Adafruit PyPortal with samd51j20

# Demo of strange group behavior group.hidden is set True before content is appended
#
import time
import board
import displayio

# start display for example with PyPortal
display = board.DISPLAY

bitmap = displayio.Bitmap(50,50, 2)
palette = displayio.Palette(2)
palette[0] = 0xAA0000
tilegrid = displayio.TileGrid(bitmap, pixel_shader=palette)

group = displayio.Group(x=(320-bitmap.width)//2, y=(240-bitmap.height)//2, max_size=1)
group.hidden=True  ##### If this statement is included before the tilegrid is appended
                   ##### onto the group, the group is incorrectly visible until
                   ##### the `group.hidden` is set False and then back to True
                   #####
                   ##### If this line is commented out, it works as expected.

print("1 group.hidden: {}".format(group.hidden))

group.append(tilegrid)
print("2 group.hidden: {}".format(group.hidden))
group.hidden = True
print("3 group.hidden: {}".format(group.hidden))

display.show(group)
display.refresh()

print("Red square should be hidden.") # Red square is visible with current code
time.sleep(5)

group.hidden=True
print("Set /`group.hidden = True/` again.  Red square should be hidden.")
print("4 group.hidden: {}".format(group.hidden))
time.sleep(5)  # Red square is visible with current code

group.hidden=False
print("Set /`group.hidden = False/`, Red square should be visible.")
print("5 group.hidden: {}".format(group.hidden))
time.sleep(5)

group.hidden=True
print("Set /`group.hidden = True/` another time.  Red square should be hidden.")
print("6 group.hidden: {}".format(group.hidden))
time.sleep(5)

group.hidden=False
print("Set /`group.hidden = False/`, Red square should be visible.")
print("7 group.hidden: {}".format(group.hidden))

while True:
    pass
@dhalbert dhalbert added this to the 6.x.x - Bug Fixes milestone Feb 12, 2021
@dhalbert dhalbert added the bug label Feb 12, 2021
@kmatch98
Copy link
Collaborator Author

The root cause of this is related to the use of two separate properties to control hidden behaviour of Group and TileGrid.

The Group contains two properties that help hide graphical content:

  • hidden
  • hidden_by_parent

I'm not clear on the logic behind hidden_by_parent so I'm interested to better understand the importance of that.

Here is cause of the issue. Whenever content is appended (and maybe inserted) into a Group, the hidden property is not transferred into the content as hidden_by_parent. Then, when the display checks which Groups refresh regions should be rendered, these artificially "non-hidden" appended display elements get displayed.

Digging a bit deeper, I see that the Group "get_refresh_areas" function doesn't check the hidden property before deciding what areas should be displayed. In contrast, the TileGrid "refresh" and "get_refresh_areas" code does check whether they are hidden.

I see two possible solutions:

  • Simple - Whenever inserting or appending content into a group, set the content's hidden_by_parent property to match the Parent's group->hidden status. Note: Will need to iterate down any content.
  • Complex - Get rid of this hidden_by_parent attribute. Instead, in Group's get_refresh_areas and refresh, if a hidden Group is encountered, don't refresh any of this Group's content. Benefit: This would allow different "depths" of hidden-ness, that is Children could retain their hidden properties even if the Parent's hidden properties changes.

Suggestions are welcome.

@tannewt
Copy link
Member

tannewt commented Feb 17, 2021

I think the simple route is your only route. The complex route risks not actually updating a portion of the screen because dirty areas only come from TileGrids IIRC. TileGrids need to know when they are hidden so they can provide the area where they were rendered last (but not where they are now.) hidden_by_parent is separate from hidden because the public hidden attribute is for the TileGrid only.

@kmatch98
Copy link
Collaborator Author

Major improvements to Group are underway: #4233
After those are implemented then I will revisit this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants