实现一个列表框
我需要为移动设备实现一个列表框。唯一相关的控件是向上和向下箭头键。列表框应显示列表中尽可能多的项目行,以适合屏幕(screen_rows),应突出显示一行(sel_row),并且如果用户在第一个项目突出显示时点击向上箭头或向下箭头,则显示应换行如果最后一个项目突出显示(也就是说,如果用户在第一个项目突出显示时点击,则应显示并突出显示最后一个项目)。向上箭头突出显示前一项,向下箭头突出显示下一项。
我已经将一些东西放在一起,但担心我在测试中遗漏了一些东西。鉴于列表框的流行,必须有一个标准的方法来做到这一点。
def up_key(self):
if self.sel_row > 0:
self.sel_row -= 1
elif self.top_item > 0: # top_item is the index of the first list item
self.top_item -= 1
elif self.top_item == 0:
if self.n_lines >= self.screen_rows: # n_lines is the number of items in the list
self.top_item = self.n_lines - self.screen_rows
self.sel_row = min(self.screen_rows-1, self.n_lines-1)
else:
self.top_item = 0
self.sel_row = self.n_lines-1
def down_key(self):
if self.sel_row < self.screen_rows-1 and self.sel_row < self.n_lines-1:
self.sel_row += 1
elif self.sel_row == self.screen_rows-1:
bottom_item = self.top_item + self.screen_rows
if bottom_item == self.n_lines:
self.top_item = 0
self.sel_row = 0
if bottom_item < self.n_lines:
self.top_item += 1
elif self.sel_row == self.n_lines-1:
self.top_item = 0
self.sel_row = 0
def set_pos(self, pos): # display item with index pos
if pos < 0:
pos = 0
elif pos >= self.n_lines:
pos = self.n_lines - 1
if pos < self.screen_rows:
self.top_item = 0
self.sel_row = pos
else:
self.sel_row = min(self.screen_rows, self.n_lines)//2 - 1
self.top_item = pos - self.sel_row
if self.top_item >= self.n_lines - self.screen_rows:
self.top_item = self.n_lines - self.screen_rows - 1
self.sel_row = pos - self.top_item - 1
编辑:在每个函数之后,我调用一个重绘屏幕函数,该函数重绘屏幕,顶部的 top_item 和突出显示的 sel-row 。
我添加了一个伪代码标签,以防有人有非 python 的版本。
I need to implement a listbox for a mobile. The only relevant controls are up and down arrow keys. The listbox should display as many rows of items from a list as will fit on the screen (screen_rows), one row should be highighted (sel_row) and the display should wrap if the user hits up arrow when the first item is highlighted or down arrow if the last item is highlighted (that is, the last item should be displayed and highlighted if the user hits up when the first item is highlighted). Up arrow highlights the previous item and down arrow highlights the next item.
I've put something together, but am concerned I've missed something in testing. There must be a standard way to do this, given the prevalence of listboxes out there.
def up_key(self):
if self.sel_row > 0:
self.sel_row -= 1
elif self.top_item > 0: # top_item is the index of the first list item
self.top_item -= 1
elif self.top_item == 0:
if self.n_lines >= self.screen_rows: # n_lines is the number of items in the list
self.top_item = self.n_lines - self.screen_rows
self.sel_row = min(self.screen_rows-1, self.n_lines-1)
else:
self.top_item = 0
self.sel_row = self.n_lines-1
def down_key(self):
if self.sel_row < self.screen_rows-1 and self.sel_row < self.n_lines-1:
self.sel_row += 1
elif self.sel_row == self.screen_rows-1:
bottom_item = self.top_item + self.screen_rows
if bottom_item == self.n_lines:
self.top_item = 0
self.sel_row = 0
if bottom_item < self.n_lines:
self.top_item += 1
elif self.sel_row == self.n_lines-1:
self.top_item = 0
self.sel_row = 0
def set_pos(self, pos): # display item with index pos
if pos < 0:
pos = 0
elif pos >= self.n_lines:
pos = self.n_lines - 1
if pos < self.screen_rows:
self.top_item = 0
self.sel_row = pos
else:
self.sel_row = min(self.screen_rows, self.n_lines)//2 - 1
self.top_item = pos - self.sel_row
if self.top_item >= self.n_lines - self.screen_rows:
self.top_item = self.n_lines - self.screen_rows - 1
self.sel_row = pos - self.top_item - 1
EDIT: after each function I call a redraw screen function, which redraws the screen with top_item at the top and sel-row highlighted.
I've added a pseudo-code tag, in case someone has a version in something that's not python.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
很少有 Python 程序从头开始实现列表框——它们通常只是取自现有的工具包。这可以解释为什么没有真正的跨工具包“标准”!-)
对于您的代码,我想
set_pos
应该在up_key
或之后立即调用>down_key
已完成(您没有完全清楚地说明这一点)。我主要担心的是两个
_key
例程之间的重复性和不对称性。当然,考虑到您的向上键和向下键的规格非常相似,您希望委托给一个采用“增量”参数(+1 或 -1)的函数。该通用函数可以首先执行self.sel_row +=increment
,然后在sel_row
仍然正常的常见情况下立即返回,即if self.top_item
= self.sel_row < self.top_item + self.screen_rows
;否则处理sel_row
已退出当前显示区域的情况,通过调整self.top_item
,如果导致不需要环绕则退出,或者最后处理环绕情况。我热衷于通过重复使用“执行一些所需的状态机会;如果现在一切正常,则返回”形式的构造来应用“扁平比嵌套更好”,而不是逻辑上更复杂的“如果做一件简单的事情就可以了” ,然后做简单的事情;否则,如果需要一些更复杂但并不可怕的事情,那么就做复杂的事情;否则,如果我们遇到非常复杂的情况,那就处理真正复杂的问题”——后者远远不够。在任何情况下都更容易出错并且更难遵循。
Few Python programs implement listboxes from scratch -- they're normally just taken from existing toolkits. That may explain why there's no real cross-toolkit "standard"!-)
Coming to your code, I imagine
set_pos
is meant to be called right after eitherup_key
ordown_key
are finished (you don't make this entirely clear).My main worry would be the repetitiousness and asymmetry between your two
_key
routines. Surely given that your specs are so similar for up and down keys, you want to delegate to a single function which takes an "increment" argument, either +1 or -1. That common function could first doself.sel_row += increment
, then immediately return in the common case wheresel_row
is still fine, i.eif self.top_item <= self.sel_row < self.top_item + self.screen_rows
; otherwise deal with the cases wheresel_row
has exited the currently displayed region, by adjustingself.top_item
, exiting if that causes no need to wraparound, or finally dealing with the wraparound cases.I'd be keen to apply "flat is better than nested" by repeatedly using constructs of the form "do some required state chance; if things are now fine, return" rather than logically more complex "if doing a simple thing will be OK, then do the simple thing; else if something a bit more complicated but not terrible is needed, then do the complicated something; else if we're in a really complicated case, deal with the really complicated problem" -- the latter is far more prone to error and harder to follow in any case.