2009-10-20 10 views
0

Je dois implémenter une zone de liste pour un mobile. Les seuls contrôles pertinents sont les flèches haut et bas. La zone de liste doit afficher autant de lignes d'éléments d'une liste que d'éléments (screen_rows), une ligne d'en-tête (sel_row) et l'affichage doit s'enrouler si l'utilisateur pointe vers le haut lorsque le premier élément est en surbrillance ou en bas si le dernier élément est surligné (c'est-à-dire que le dernier élément doit être affiché et mis en surbrillance si l'utilisateur frappe lorsque le premier élément est en surbrillance). La flèche vers le haut met en évidence l'élément précédent et la flèche vers le bas met en évidence l'élément suivant.Implémenter une zone de liste

J'ai mis quelque chose ensemble, mais je suis inquiet J'ai manqué quelque chose dans le test. Il doit y avoir un moyen standard de le faire, étant donné la prévalence des listes de diffusion.

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: après chaque fonction I appeler une fonction d'écran d'emboutissage de reprise, qui retrace l'écran avec top_item à la rangée supérieure et sel mis en surbrillance.

J'ai ajouté une balise de pseudo-code, au cas où quelqu'un aurait une version dans quelque chose qui n'est pas python.

Répondre

1

Peu de programmes Python implémentent des listboxes à partir de rien - ils sont normalement extraits de toolkits existants. Cela peut expliquer pourquoi il n'y a pas de contre-toolkit réel « standard » -!)

En venant à votre code, j'imagine set_pos est destiné à être appelé juste après soit up_key ou down_key sont finis (vous ne faites pas tout à fait clair). Mon principal souci serait la répétitivité et l'asymétrie entre les deux routines _key. Sûrement, étant donné que vos spécifications sont si similaires pour les clés haut et bas, vous voulez déléguer à une seule fonction qui prend un argument "incrément", soit +1 ou -1. Cette fonction commune peut d'abord faire self.sel_row += increment, puis retourner immédiatement dans le cas courant où sel_row est toujours correct, c'est-à-dire if self.top_item <= self.sel_row < self.top_item + self.screen_rows; sinon traiter les cas où sel_row a quitté la région actuellement affichée, en ajustant self.top_item, en quittant si cela ne nécessite pas de bouclage, ou en traitant finalement les cas de bouclage. Je voudrais appliquer "plat est mieux que imbriqué" en utilisant à plusieurs reprises des constructions de la forme "faire un certain état requis, si les choses sont maintenant bien, retour" plutôt que logiquement plus complexe "si faire un simple Tout ira bien, alors faites la chose simple, sinon si quelque chose d'un peu plus compliqué mais pas terrible est nécessaire, alors faites le quelque chose de compliqué, sinon nous sommes dans un cas vraiment compliqué, face au problème vraiment compliqué. ce dernier est beaucoup plus enclin à l'erreur et plus difficile à suivre dans tous les cas.

+0

J'avais l'habitude de voir les listboxes implémentées en c ou C++ dans les premières années de programmation de gui, mais je ne trouve aucun exemple. En tout cas, je vais voir si changer comme vous le suggérez rend les choses plus simples et revenir, le cas échéant – foosion

+0

@foosion, oui, avant l'émergence de cadres GUI et des widgets avec des fonctionnalités raisonnables, quand on programmé à la base xlib ou le même, on a écrit ses propres widgets - été là, fait cela, mais, il y a * LONG * temps! -) –

+0

@Alex, cela ne fait que 20 ans environ :-) – foosion