问题
I'd like to implement some hinting as to whether there remains items below or above the list of visible items in an urwid.ListBox
when I scroll it up or down. The 'scroll down' hint should appear only when there remains items after the last visible item and it should disappear when the last, visible item is the last item in the list. The reverse applies with the 'scroll up' hint.
I then need to know how many visible items there is in the list. Is there a way to retrieve the number of visible items in a list box, which I suppose is equal to the height of the list box, right?
Here's a starting point of what I'd like to check:
# This example is based on https://cmsdk.com/python/is-there-a-focus-changed-event-in-urwid.html
import urwid
def callback():
index = str(listbox.get_focus()[1])
debug.set_text("Index of selected item: " + index)
captions = "A B C D E F".split()
debug = urwid.Text("Debug")
items = [urwid.Button(caption) for caption in captions]
walker = urwid.SimpleListWalker(items)
listbox = urwid.ListBox(walker)
urwid.connect_signal(walker, "modified", callback)
frame = urwid.Frame(body=listbox, header=debug)
urwid.MainLoop(frame).run()
The idea is to know if the listbox is fully visible within the frame when the terminal window is shrunk or not tall enough to display everything, i.e. frame.height >= listbox.height
.
回答1:
So, here is one way of doing this by subclassing urwid.ListBox, we can add an attribute all_children_visible
which is set at the times when we know the size of the widget (that is, when rendering or when handling an input event).
The sample code, based on the sample you provided:
import string
import urwid
class MyListBox(urwid.ListBox):
all_children_visible = True
def keypress(self, size, *args, **kwargs):
self.all_children_visible = self._compute_all_children_visible(size)
return super(MyListBox, self).keypress(size, *args, **kwargs)
def mouse_event(self, size, *args, **kwargs):
self.all_children_visible = self._compute_all_children_visible(size)
return super(MyListBox, self).mouse_event(size, *args, **kwargs)
def render(self, size, *args, **kwargs):
self.all_children_visible = self._compute_all_children_visible(size)
return super(MyListBox, self).render(size, *args, **kwargs)
def _compute_all_children_visible(self, size):
n_total_widgets = len(self.body)
middle, top, bottom = self.calculate_visible(size)
n_visible = len(top[1]) + len(bottom[1])
if middle:
n_visible += 1
return n_total_widgets == n_visible
def callback():
debug.set_text(
"Are all children visible? {}\n".format(listbox.all_children_visible)
)
captions = list(string.uppercase + string.lowercase)
# uncomment this line to test case of all children visible:
# captions = list(string.uppercase)
debug = urwid.Text("Debug")
items = [urwid.Button(caption) for caption in captions]
walker = urwid.SimpleListWalker(items)
listbox = MyListBox(walker)
urwid.connect_signal(walker, "modified", callback)
frame = urwid.Frame(body=listbox, header=debug)
urwid.MainLoop(frame).run()
I'm not sure how well this performs (I haven't tested it extensively), so I'm curious how this will perform for your case -- let me know how it goes. :)
来源:https://stackoverflow.com/questions/48737120/how-do-i-determine-the-number-of-visible-items-in-a-listbox-with-urwid