How to show multiple items on one page #183
Replies: 1 comment 1 reply
-
Hey there, let's start with a couple of minor remarks on your code example, before we look at ways to shorten it:
With the above changes and some minor adjustments, your code will work nicely to split up a larger number of items over multiple pages: import alfred3 as al
exp = al.Experiment()
@exp.member
class Questionnaire(al.Section):
title = "Questionnaire"
def on_exp_access(self):
list_items = [
{"name": "i1", "toplab": "This is item 1."},
{"name": "i2", "toplab": "This is item 2."},
{"name": "i3", "toplab": "This is item 3."},
{"name": "i4", "toplab": "This is item 4."},
{"name": "i5", "toplab": "This is item 5."},
{"name": "i6", "toplab": "This is item 6."},
{"name": "i7", "toplab": "This is item 7."},
{"name": "i8", "toplab": "This is item 8."},
{"name": "i9", "toplab": "This is item 9."},
{"name": "i10", "toplab": "This is item 10."}
]
list_choices = ["1", "2", "3", "4", "5"]
list_labels = ["not at all", "seldomnly", "every now and then", "often", "always"]
first_5 = al.Page(name="first_5")
first_5 += al.ButtonLabels(*list_labels, leftlab=" ", button_style="btn-secondary")
for item in list_items[0:5]:
first_5 += al.VerticalSpace()
first_5 += al.SingleChoiceButtons(*list_choices,
leftlab=item.get('toplab'),
name=item.get('name'),
width="full",
force_input=True,
font_size="small"
)
second_5 = al.Page(name="second_5")
second_5 += al.ButtonLabels(*list_labels, leftlab=" ", button_style="btn-secondary")
for item in list_items[5:10]:
second_5 += al.VerticalSpace()
second_5 += al.SingleChoiceButtons(*list_choices,
leftlab=item.get('toplab'),
name=item.get('name'),
width="full",
force_input=True,
font_size="small"
)
self += first_5
self += second_5
if __name__ == "__main__":
exp.run() However, there is a way to shorten your code by combining a for-loop and a while-loop. With this, we can use the pop() function to access and at the sime time remove items from the item list, and our while-loop will only run until item_list is empty: import alfred3 as al
exp = al.Experiment()
@exp.member
class Questionnaire(al.Section):
title = "Questionnaire"
def on_exp_access(self):
list_items = [
{"name": "i1", "toplab": "This is item 1."},
{"name": "i2", "toplab": "This is item 2."},
{"name": "i3", "toplab": "This is item 3."},
{"name": "i4", "toplab": "This is item 4."},
{"name": "i5", "toplab": "This is item 5."},
{"name": "i6", "toplab": "This is item 6."},
{"name": "i7", "toplab": "This is item 7."},
{"name": "i8", "toplab": "This is item 8."},
{"name": "i9", "toplab": "This is item 9."},
{"name": "i10", "toplab": "This is item 10."}
]
list_choices = ["1", "2", "3", "4", "5"]
list_labels = ["not at all", "seldomnly", "every now and then", "often", "always"]
count = 1
while list_items:
page = al.Page(name=f"questionnaire_{count}")
page += al.ButtonLabels(*list_labels, leftlab=" ", button_style="btn-secondary")
for i in range(5):
item = list_items.pop(0) # Return and remove the first list item
page += al.VerticalSpace()
page += al.SingleChoiceButtons(
*list_choices,
leftlab=item['toplab'],
name=item['name'],
width="full",
force_input=True,
font_size="small"
)
self += page
count += 1
if __name__ == "__main__":
exp.run() Further explanation: I use the new variable count to set the page name in each iteration of my while loop. The loop itself will only run until there are no items left in item_list and in each iteration of the for-loop, I remove an item from the list. On first sight, this might seem a little complex, but there is a big advantage to this variant, other than not needing to copy and paste the for-loop: By adding two lines of code, I can make the example work for a variable number of items: import alfred3 as al
exp = al.Experiment()
@exp.member
class Questionnaire(al.Section):
title = "Questionnaire"
def on_exp_access(self):
list_items = [
{"name": "i1", "toplab": "This is item 1."},
{"name": "i2", "toplab": "This is item 2."},
{"name": "i3", "toplab": "This is item 3."},
{"name": "i4", "toplab": "This is item 4."},
{"name": "i5", "toplab": "This is item 5."},
{"name": "i6", "toplab": "This is item 6."},
{"name": "i7", "toplab": "This is item 7."},
{"name": "i8", "toplab": "This is item 8."},
{"name": "i9", "toplab": "This is item 9."},
{"name": "i10", "toplab": "This is item 10."}
]
list_choices = ["1", "2", "3", "4", "5"]
list_labels = ["not at all", "seldomnly", "every now and then", "often", "always"]
count = 1
while list_items:
page = al.Page(name=f"questionnaire_{count}")
page += al.ButtonLabels(*list_labels, leftlab=" ", button_style="btn-secondary")
for i in range(5):
# The following two lines will skip the remaining iterations when the
# item list runs out of items, giving the code way more flexibility.
if not list_items:
continue
item = list_items.pop(0) # Return and remove the first list item
page += al.VerticalSpace()
page += al.SingleChoiceButtons(
*list_choices,
leftlab=item['toplab'],
name=item['name'],
width="full",
force_input=True,
font_size="small"
)
self += page
count += 1
if __name__ == "__main__":
exp.run() With this final variant, you can change the number in range() to any number you like and you can add or remove items from item_list without having to change anything else. The combined while- and for-loops will run until all items in item_list have been added. |
Beta Was this translation helpful? Give feedback.
-
I would like to elegantly show multiple items out of a big item pool on several pages. I have 60 items and would like to show 5 per page. Here is my solution so far. The minimal code doesn't quite work the way the proper experiment does, but for these purposes it should do.
To create multiple pages with only 5 items each I have to repeat the same code several times (12 times for 60 items) and add each page at the bottom. This works but perhaps there is a more elegant way!
list_items = [
{"name": "1", "toplab": "This is item 1."},
{"name": "2", "toplab": "This is item 2."},
{"name": "3", "toplab": "This is item 3."},
{"name": "4", "toplab": "This is item 4."},
{"name": "5", "toplab": "This is item 5."},
{"name": "6", "toplab": "This is item 6."},
{"name": "7", "toplab": "This is item 7."},
{"name": "8", "toplab": "This is item 8."},
{"name": "9", "toplab": "This is item 9."},
{"name": "10", "toplab": "This is item 10."}
]
list_choices = [
"1",
"2",
"3",
"4",
"5",
]
list_labels = [
"not at all",
"seldomnly",
"every now and then",
"often",
"always"
]
@exp.member
class questionnaire(al.Section):
title = "Questionnaire"
if name == "main":
exp.run()
Beta Was this translation helpful? Give feedback.
All reactions