Randomly removed button (or doesn't render it?) from custom widget
PSMusicalRoc opened this issue · comments
My custom widget named EmptySlot
is supposed to be a widget that has a background widget with a button widget over it. For the most part, I've done that, however when I load my program, which iterates over 2 loops and creates a 3x3 grid filled with these widgets, the program randomly allows some of the created widgets to show (or have) their buttons, while others don't have them. Which ones happen to have their buttons seems random. I was wondering if someone could help me figure out why the widget is bugging, and if there is a better way to create the EmptySlot
widget.
What happens: https://drive.google.com/file/d/1QLaoDQX6urg7_OfGs_zdPt13hX90E6gE/view?usp=sharing
Code:
main.py
:
import pyglet, glooey
import Widgets
gui_batch = pyglet.graphics.Batch()
window = pyglet.window.Window(1920, 1080,
caption="Smash Scoreboard 4.0")
gui = glooey.Gui(window, batch=gui_batch)
grid = glooey.Grid(3, 3)
for y in range(3):
for x in range(3):
grid[x, y] = Widgets.EmptySlot()
gui.add(grid)
@window.event
def on_draw():
window.clear()
gui_batch.draw()
pyglet.app.run()
__init__.py
in the Widgets module
import glooey, pyglet
##################################
# WIDGET PRIMITIVES DEFINED HERE #
##################################
class Slot(glooey.Background):
custom_center = pyglet.resource.texture('Widgets/Textures/BaseWidget/DefaultBackgroundColor.png')
custom_top = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetTop.png')
custom_bottom = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetBottom.png')
custom_left = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetLeft.png')
custom_right = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetRight.png')
custom_top_left = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetTopLeft.png')
custom_top_right = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetTopRight.png')
custom_bottom_left = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetBottomLeft.png')
custom_bottom_right = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetBottomRight.png')
class AddButton(glooey.Button):
class Background(glooey.Background):
custom_center = pyglet.resource.texture('Widgets/Textures/BaseWidget/WidgetAdd.png')
class EmptySlot(glooey.Widget):
def __init__(self):
super().__init__()
self.background = Slot()
self._attach_child(self.background)
self.board = glooey.Board()
button = AddButton()
self.board.add(button, left=50, bottom=50, width=1, height=1)
self._attach_child(self.board)
def do_claim(self):
return self.background.do_claim()
#####################################
# END WIDGET PRIMITIVES DEFINITIONS #
#####################################
Update:
I ended up fixing the weird inconsistency by inheriting from a Stack
, which gave my widget the functionality it needed. However, I would like an explanation as to why my first attempt was inconsistent if anyone has an answer
New Class Definition
class EmptySlot(glooey.Stack):
def __init__(self):
super().__init__()
self.background = Slot()
self.button = AddButton()
self.board = glooey.Board()
self.board.add(self.button, right=50, bottom=50, height=1, width=1)
self.add_back(self.background)
self.add_front(self.board)
I can't see the image you uploaded (it appears to be 382 MB?!), so this is a little bit of a guess, but I'm pretty sure the problem is that you didn't reimplement the _do_regroup_children()
method. This method is important here because groups (specifically, OrderedGroup
) are how you make control z-ordering in pyglet. By default, all the children of a widget just go in the same group as that widget. But when two widgets in the same group overlap, it's basically random which one will appear in front.
Here's an example of how you might handle this:
from pyglet.graphics import OrderedGroup
def _do_regroup_children(self):
self.background._regroup(OrderedGroup(1, self.group))
self.board._regroup(OrderedGroup(2, self.group))
(Note: I can't remember off-hand whether higher- or lower-numbered groups go in front, so you might have to switch the numbers.)
All that said, if you haven't already, I'd recommend reading the tutorial on composing widgets. It goes over some examples very similar to what you're trying to do here. In particular, I would probably recommend using Stack
rather than writing your own _do_regroup_children()
method, just because it'll keep your code simpler. But I wouldn't recommend inheriting from Stack
, because Stack
does a bunch of things that don't make sense for your widget (e.g. adding/removing widgets). Instead, I would inherit from Widget
, add a single Stack
as a child, then add the Background
and the Button
to the Stack
. (If that doesn't make sense, the tutorial says basically the same thing in more detail.)
Thank you for that, doing things with a Stack
worked beautifully! Now for another, unrelated to topic, question (I'm not sure if that should go in its own issue or not, still figuring out the customs of GitHub!) When I try to implement a ScrollBox
widget with a 6x6 grid that is too big attached to it, it throws a sizing error. Specifically:
RuntimeError: Gui(id=2040) is only 300x300, but its children are 431x431.
For context, here is the code I've been using. It's being put into a 300x300 window (as shown in the error log):
class TestScroll(glooey.ScrollBox):
def __init__(self):
super().__init__()
self.grid = Grid(6, 6)
for x in range(6):
for y in range(6):
self.grid[y, x] = TextInputButton((0, 0))
self.add(self.grid)
...where Grid
is a custom grid inherited from your Grid function that has 5 cell padding on it, and TextInputButton
is a simple button with an image on it.
Any idea how to remedy this?
It's probably better to open new issues for unrelated questions, because I think that makes it easier for other people to find the issue if they have a similar question. It also makes it a little more clear what's meant if the issue gets referenced in a commit or a PR. But that's just for future reference, don't worry about creating a new issue for this question.
Regarding the actual question: I think the problem is that the TestScroll
doesn't define either the HBar
or VBar
inner classes. Glooey interprets that to mean that the box is not scrollable in either the horizontal or vertical directions, and therefore the content of the box must fit within the window. I realize that this isn't actually mentioned anywhere in the docs, and it's a pretty easy mistake to make, so I'll definitely try to update the docs and make this more clear.
Awesome, thanks! That suggestion worked, although I figured out that defining the Grid
as being a 6x6 grid was the mistake. I had only wanted vertical scrolling, and I accidentally kept the Grid too large to fit in the ScrollBox
.