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

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.

4

1 回答 1

1

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.

于 2009-10-20T15:30:14.800 回答