实现一个列表框

发布于 2024-08-08 12:40:11 字数 1956 浏览 6 评论 0原文

我需要为移动设备实现一个列表框。唯一相关的控件是向上和向下箭头键。列表框应显示列表中尽可能多的项目行,以适合屏幕(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绿光 2024-08-15 12:40:11

很少有 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 either up_key or down_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 do self.sel_row += increment, then immediately return in the common case where sel_row is still fine, i.e if self.top_item <= self.sel_row < self.top_item + self.screen_rows; otherwise deal with the cases where sel_row has exited the currently displayed region, by adjusting self.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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文