Coucou JF et tous,
Tu dis :
1. Quel moyen le système me fournirait-il pour connaître le nombre
d'éléments de cette liste à un instant donné? Je n'ai pas trouvé de
manière évidente en tout cas...
Hé bien tout simplement grâce à la méthode GetCount() de la classe
wx.ListBox.
Dans le cas de ton exemple, ça donnerait ce qui suit :
self.listbox.GetCount() au lieu de cette variable self.len que tu as
utilisée.
Tu dis :
2. Les déplacements dans la liste que je crée, ne "bouclent pas".
Pour ce que je voulais en faire, ça ne m'arrange pas forcément, parce
qu'il s'agit de choisir entre deux éléments, et peu importe que l'un
soit en position 1 et l'autre en position 2, c'est sur le contenu que
je dois choisir.
Existerait-il un paramètre qui régit le "bouclage"?
Malheureusement, le wxPython n'a pas prévu ce comportement pour les
wx.ListBox, même dans ces implémentations les plus récentes.
Il n'existe donc pas de style particulier, ni de méthode d'ailleurs
pouvant gérer cela.
Mais si tu as plus d'un tour dans ton sac, tu devrais pouvoir créer
toi-même une implémentation qui te permettrait de faire en sorte que la
navigation verticale parmi les items de ta wx.ListBox soit cyclique.
Tout simplement en utilisant les événements, l'événement wx.EVT_KEY_UP
peut par exemple très bien gérer ce type de comportement.
Je te rejoins ton code avec un événement wx.EVT_KEY_UP ainsi que
quelques commentaires pour le nombre total d'items de ta wx.ListBox.
Je t'en souhaite bonne réception et reste à ta dispo si besoin.
Bien amicalement,
Abdel.
Le 04/12/2017 à 21:41, Jean-François Colas a écrit :
Hello la ML,
J'essaie de jouer un peu avec les listes en WxPython. J'ai vu qu'il
existait un objet ListBox, sur lequel je me pose deux questions:
1. Quel moyen le système me fournirait-il pour connaître le nombre
d'éléments de cette liste à un instant donné? Je n'ai pas trouvé de
manière évidente en tout cas...
2. Les déplacements dans la liste que je crée, ne "bouclent pas". Pour
ce que je voulais en faire, ça ne m'arrange pas forcément, parce qu'il
s'agit de choisir entre deux éléments, et peu importe que l'un soit en
position 1 et l'autre en position 2, c'est sur le contenu que je dois
choisir. Existerait-il un paramètre qui régit le "bouclage"?
Pour illustrer un peu la question 1, je suis parti d'un exemple, tiré
d'une doc en anglais qui me plaît bien, dont le titre est grosso modo:
WXPython ZetCode tutorial... J'ai mis l'exemple en pJ.
J'ai voulu y ajouter la sélection automatique d'un élément selon
l'action effectuée; et du coup, pour gérer cette histoire de nombre
d'éléments, j'y ai inséré du code, les lignes en question sont
repérées par # jf. Est-ce que vraiment j'étais obligé de passer par là
pour garder trace du nombre d'éléments, sachant que Jaws est capable,
lui, de me l'indiquer?
Merci,
J.-F.
#!/usr/bin/python
# -*- coding: utf-8 -*-
# listbox.py
import wx
ID_NEW = 1
ID_RENAME = 2
ID_CLEAR = 3
ID_DELETE = 4
class ListBox(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(350, 220))
panel = wx.Panel(self, -1)
hbox = wx.BoxSizer(wx.HORIZONTAL)
self.listbox = wx.ListBox(panel, -1)
#self.len = 0 # nombre d'elements de la liste (cette ligne a
entièrement été mise en commentaire, explication plus bas).
# Pas besoin d'initialiser une variable self.len pour le nombre
d'items, il existe la méthode GetCount, qui permet de donner le nombre
d'élément de ta wx.ListBox.
self.up = 0 # Pour initialiser une variable pour la navigation vers le
haut dans la liste des items.
self.down = 0 # Pour initialiser une variable pour la navigation vers
le bas dans la liste des items.
hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)
btnPanel = wx.Panel(panel, -1)
vbox = wx.BoxSizer(wx.VERTICAL)
new = wx.Button(btnPanel, ID_NEW, 'New', size=(90, 30))
ren = wx.Button(btnPanel, ID_RENAME, 'Rename', size=(90, 30))
dlt = wx.Button(btnPanel, ID_DELETE, 'Delete', size=(90, 30))
clr = wx.Button(btnPanel, ID_CLEAR, 'Clear', size=(90, 30))
self.Bind(wx.EVT_BUTTON, self.NewItem, id=ID_NEW)
self.Bind(wx.EVT_BUTTON, self.OnRename, id=ID_RENAME)
self.Bind(wx.EVT_BUTTON, self.OnDelete, id=ID_DELETE)
self.Bind(wx.EVT_BUTTON, self.OnClear, id=ID_CLEAR)
self.Bind(wx.EVT_LISTBOX_DCLICK, self.OnRename)
self.listbox.Bind(wx.EVT_KEY_UP, self.OnKeyUp) # Pour lanavigation
cyclique parmi les items de notre wx.ListBox.
vbox.Add((-1, 20))
vbox.Add(new)
vbox.Add(ren, 0, wx.TOP, 5)
vbox.Add(dlt, 0, wx.TOP, 5)
vbox.Add(clr, 0, wx.TOP, 5)
btnPanel.SetSizer(vbox)
hbox.Add(btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
panel.SetSizer(hbox)
self.Centre()
self.Show(True)
def NewItem(self, event):
text = wx.GetTextFromUser('Enter a new item', 'Insert dialog')
if text != '':
self.listbox.Append(text)
self.listbox.SetFocus() # jf
self.listbox.SetSelection(self.listbox.GetCount()-1) # pour mettre
le focus sur le dernier item.
def OnKeyUp(self, event):
"""
Pour gérer la navigation cyclique parmi les items de notre wx.ListBox.
"""
# On récupère le keyCode de la touche pressée dans la variable key.
key = event.GetKeyCode()
# On récupère le nombre total d'items dans la variable max.
max = self.listbox.GetCount()
# On récupère l'index de l'item actuellement sélectionné dans la
variable curItem.
curItem = event.GetEventObject().GetSelection()
if key == wx.WXK_DOWN:
# On a pressé la touche flèche basse.
if max > 1 and curItem == max -1:
# On incrémente self.down.
self.down += 1
if self.down == 2:
# Pour que le dernier item soit lu ne serait-ce qu'une fois
avant de revenir au début.
self.listbox.SetSelection (0)
# On réinitialise self.down et self.up.
self.down=0
self.up = 0
if key == wx.WXK_UP:
#On a pressé la touche flèche haute.
if max > 1 and curItem == 0:
# On décrémente self.up.
self.up -= 1
if self.up == -2:
# Pour que le premier item soit lu ne serait-ce qu'une fois
avant d'aller à la fin.
self.listbox.SetSelection (max-1)
# On réinitialise self.up et self.down.
self.up=0
self.down=0
def OnRename(self, event):
sel = self.listbox.GetSelection()
text = self.listbox.GetString(sel)
renamed = wx.GetTextFromUser('Rename item', 'Rename dialog', text)
if renamed != '':
self.listbox.Delete(sel)
self.listbox.Insert(renamed, sel)
self.listbox.SetFocus() # Pour revenir à la liste.
self.listbox.SetSelection(sel) # Pour sélectionner l'item
nouvellement renommé.
def OnDelete(self, event):
sel = self.listbox.GetSelection()
if sel != -1:
self.listbox.Delete(sel)
if self.listbox.GetCount() > 0: # S'il reste plus de 0 items.
self.listbox.SetFocus() # jf.
newSel = 0 if sel ==0 else self.listbox.GetCount() -1 # On
redéfinit l'item à sélectionner.
self.listbox.SetSelection(newSel) # jf
def OnClear(self, event):
self.listbox.Clear()
self.listbox.SetFocus() # jf
app = wx.App()
ListBox(None, -1, 'ListBox')
app.MainLoop()