-
Notifications
You must be signed in to change notification settings - Fork 26
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
No Listbox widget #28
Comments
On a side note I would be willing to try to implement some of these widgets if you had some basic documentation on how to add new widgets to LUI |
Right now there are only select boxes. Listboxes seem useful, although I don't know when I'd find some time to implement them. There are also people who already contributed something, you might be able to meet them in the panda3d irc, they probably can help you with that, too. |
So I spent most of my night getting the ground work laid for a functional listbox widget. Functionally I actually got one working, as I mostly reused the code from the Radio and RadioGroup. The last major step I need to make is removing the O from the left of the bullet. But when I comment out the line
in class LUIListBoxOption the vertical alignment of it all blows up and looks like this Here is the source code of what I got so far. Do you have any clue what is causing the bad vertical alignment? from LUIObject import LUIObject
from LUISprite import LUISprite
from LUILabel import LUILabel
from LUILayouts import LUICornerLayout, LUIHorizontalStretchedLayout
from LUIInitialState import LUIInitialState
from LUIScrollableRegion import LUIScrollableRegion
from LUIVerticalLayout import LUIVerticalLayout
from functools import partial
__all__ = ["LUIListbox"]
class LUIListbox(LUIObject):
""" Selectbox widget, showing several options whereas the user can select
only one. """
def __init__(self, width=200, height=200, options=None, selected_option=None, **kwargs):
""" Constructs a new selectbox with a given width """
LUIObject.__init__(self, x=0, y=0, w=width + 4, h=height + 4, solid=True)
LUIInitialState.init(self, kwargs)
# The selectbox has a small border, to correct this we move it
self.margin.left = -2
self._bg_layout = LUIScrollableRegion(parent=self, width="100%")
self._v_layout = LUIVerticalLayout(parent=self._bg_layout)
self._option_group = LUIListboxOptionGroup()
for i in range(1, 40):
LUIListboxOption(parent=self._v_layout.cell(), label=str(i), group=self._option_group)
class LUIListboxOptionGroup(LUIObject):
""" Simple helper to group a bunch of LUIListOption and ensure only one is
checked at one timem """
def __init__(self):
""" Constructs a new group without any ListOptiones inside """
self._boxes = []
self._selected_box = None
def register_box(self, box):
""" Registers a box to the collection """
if box not in self._boxes:
self._boxes.append(box)
def set_active_box(self, active_box):
""" Internal function to set the active box """
for box in self._boxes:
if box is not active_box:
box._update_state(False)
box._label.alpha = 1.0
else:
box._label.alpha = 0.3
box._update_state(True)
self._selected_box = active_box
def get_active_box(self):
""" Returns the current selected box """
return self._selected_box
active_box = property(get_active_box, set_active_box)
def get_active_value(self):
""" Returns the value of the current selected box (or None if none is
selected) """
if self._selected_box is None:
return None
return self._selected_box.get_value()
active_value = property(get_active_value)
class LUIListboxOption(LUIObject):
""" A radiobox which can be used in combination with a LUIListboxOptionGroup """
def __init__(self, parent=None, group=None, value=None, active=False, label=u"Option", **kwargs):
""" Constructs a new radiobox. group should be a handle to a LUIListboxOptionGroup.
value will be the value returned by group.value, in case the box was
selected. By default, the radiobox is not active. """
assert group is not None, "LUIListboxOption needs a LUIListboxOptionGroup!"
LUIObject.__init__(self, x=0, y=0, solid=True)
self._sprite = LUISprite(self, "Radiobox_Default", "skin") # Removing me causes the vertical problem
self._label = LUILabel(parent=self, text=label, margin=(0, 0, 0, 23),
center_vertical=True)
self._value = value
self._active = False
self._hovered = False
self._group = group
self._group.register_box(self)
if active:
self.set_active()
if parent:
self.parent = parent
LUIInitialState.init(self, kwargs)
def on_click(self, event):
""" Internal onclick handler. Do not override. """
self.set_active()
def on_mouseover(self, event):
""" Internal mouseover handler """
self._hovered = True
self._update_sprite()
def on_mouseout(self, event):
""" Internal mouseout handler """
self._hovered = False
self._update_sprite()
def set_active(self):
""" Internal function to set the radiobox active """
if self._group is not None:
self._group.set_active_box(self)
else:
self._update_state(True)
""" Internal method to select an option """
def get_value(self):
""" Returns the value of the radiobox """
return self._value
def set_value(self, value):
""" Sets the value of the radiobox """
self._value = value
value = property(get_value, set_value)
def get_label(self):
""" Returns a handle to the label, so it can be modified (e.g. change
its text) """
return self._label
label = property(get_label)
def _update_state(self, active):
""" Internal method to update the state of the radiobox. Called by the
LUIListboxOptionGroup """
self._active = active
self.trigger_event("changed")
self._update_sprite()
def on_mousedown(self, event):
""" Internal onmousedown handler. Do not override. """
self._sprite.color = (0.86, 0.86, 0.86, 1.0)
def on_mouseup(self, event):
""" Internal onmouseup handler. Do not override. """
self._sprite.color = (1, 1, 1, 1)
def _update_sprite(self):
""" Internal function to update the sprite of the radiobox """
img = "Radiobox_Active" if self._active else "Radiobox_Default"
if self._hovered:
img += "Hover"
self._sprite.set_texture(img, "skin") |
First of all, thanks for your effort! Do you see any error messages on the console? Make sure you also comment the usage of self._sprite in the member methods (on_mousedown, on_mouseup, etc..). Also, try removing the center_vertical option from the Label (self._label). It's a while since I programmed it, but I believe it might cause issues since then the label will have no height then. Best regards, |
Okay that worked well. But how would you suggest changing the background color of the label and having it expand to the entire region? I need to do this for visuals and so that the user does not have to click on the text directly to activate the option. It also appears like it is a bit offset to the right still; I am not sure what is causing that. |
The offset to the right is because the label has some margin. If you remove the |
I can set either the LUIListboxOption or the LUILabel inside of it to "100%" and it will not do the expected behavior. Perhaps this serves as the example you were talking about in this issue |
You will have to set the width of both the LUIListboxOption and the LUILabel to 100%. Does it work then? |
Same behavior if I specify it twice. |
Hm, I will have a look then. Could you tell me what |
|
This seems somewhat incomplete, can you try calling it after a second or so, e.g. using taskMgr.doMethodLater ? |
|
Can't see anything obvious, I will take a look when I find some time .. For the meantime you could try setting a hardcoded width, e.g. 200 or so |
I finished my listbox with the only issue being it does not adjust to the theme color. Any clue how I can do that? After that I will email you the file so you can add it to the repo. PR seems overkill for this. |
Could you tell me how to make it so that I can override the click, mouseup, mousedown, etc events so users can implement custom behaviors for their listboxes? |
Sorry for the late reply. To make the listbox adjust to the theme color, you should probably make a sprite which is the background of your list items (Right now I suppose you use the "blank" sprite). Advantage of that is also that users might make their custom background image instead of a solid color (not sure if this would look any good though). The list looks cool, although I would probably add some padding to the text (E.g. text.padding.left = 5 or so). Not sure what you mean with overriding events. You can either add Tbh, I would prefer a pull request when the listbox is done, since this is easier to merge, and also shows the correct git history then (In case somebody has questions about the code or so) |
There is no support for a listbox currently, is there any plans to get one implemented?
Here is an example of a listbox
This is a pretty important GUI element to have available
The text was updated successfully, but these errors were encountered: