[vc_row][vc_column][vc_column_text]Recientemente estuvimos revisando sobre cómo implementar, arrastrar y soltar elementos en un wx.ListCtrl o en un ObjectListView. Desafortunadamente, ninguno de los funciones tiene esta función incorporada, aunque si encontré un artículo en la wiki de wxPython que muestra una forma de arrastrar y colocar los elementos en un ListCtrl.
Sin embargo, implementar algunos botones para mover elementos en un widget ObjectListView debería ser más fácil de implementar. Entonces, en eso se enfocará este artículo.[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]
Cambiando el orden de los elementos
Si no tiene wxPython y ObjectListView instalados, debe utilizar pip para instalarlos:
1 | pip install wxPython objectlistview |
Cuando lo haya realizado, en su IDE favorito (estamos utilizando PyCharm con Python 3) e ingrese el siguiente código:[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | import wx from ObjectListView import ObjectListView, ColumnDefn class Book(object): """ Model of the Book object Contains the following attributes: 'ISBN', 'Author', 'Manufacturer', 'Title' """ def __init__(self, title, author, isbn, mfg): self.isbn = isbn self.author = author self.mfg = mfg self.title = title def __repr__(self): return "<Book: {title}>".format(title=self.title) class MainPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) self.current_selection = None self.products = [Book("wxPython in Action", "Robin Dunn", "1932394621", "Manning"), Book("Hello World", "Warren and Carter Sande", "1933988495", "Manning"), Book("Core Python Programming", "Wesley Chun", "0132269937", "Prentice Hall"), Book("Python Programming for the Absolute Beginner", "Michael Dawson", "1598631128", "Course Technology"), Book("Learning Python", "Mark Lutz", "0596513984", "O'Reilly") ] self.dataOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) self.setBooks() # Allow the cell values to be edited when double-clicked self.dataOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK # create up and down buttons up_btn = wx.Button(self, wx.ID_ANY, "Up") up_btn.Bind(wx.EVT_BUTTON, self.move_up) down_btn = wx.Button(self, wx.ID_ANY, "Down") down_btn.Bind(wx.EVT_BUTTON, self.move_down) # Create some sizers mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(self.dataOlv, 1, wx.ALL|wx.EXPAND, 5) mainSizer.Add(up_btn, 0, wx.ALL|wx.CENTER, 5) mainSizer.Add(down_btn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(mainSizer) def move_up(self, event): """ Move an item up the list """ self.current_selection = self.dataOlv.GetSelectedObject() data = self.dataOlv.GetObjects() if self.current_selection: index = data.index(self.current_selection) if index > 0: new_index = index - 1 else: new_index = len(data)-1 data.insert(new_index, data.pop(index)) self.products = data self.setBooks() self.dataOlv.Select(new_index) def move_down(self, event): """ Move an item down the list """ self.current_selection = self.dataOlv.GetSelectedObject() data = self.dataOlv.GetObjects() if self.current_selection: index = data.index(self.current_selection) if index < len(data) - 1: new_index = index + 1 else: new_index = 0 data.insert(new_index, data.pop(index)) self.products = data self.setBooks() self.dataOlv.Select(new_index) def setBooks(self): self.dataOlv.SetColumns([ ColumnDefn("Title", "left", 220, "title"), ColumnDefn("Author", "left", 200, "author"), ColumnDefn("ISBN", "right", 100, "isbn"), ColumnDefn("Mfg", "left", 180, "mfg") ]) self.dataOlv.SetObjects(self.products) class MainFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title="ObjectListView Demo", size=(800,600)) panel = MainPanel(self) self.Show() if __name__ == "__main__": app = wx.App(False) frame = MainFrame() app.MainLoop() |
[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]El código más relevante en este ejemplo son los métodos move_up() y move_down(). Cada uno de estos métodos verificará si tiene seleccionado un elemento en el widget ObjectListView. También captará el contenido actual de los widgets. Si tiene un elemento seleccionado, tomará el índice de ese elemento de los datos del widget ObjectListView que tomamos cuando llamamos a GetObjects(). Entonces podemos usar este índice para determinar si debemos incrementar (move_down) o disminuir(move_up) el índice dependiendo de cual de los botones presionemos.
Después de actualizar la lista con las posiciones modificadas, actualizamos self.products, que es la variable de clase que usamos en setBooks() para actualizar nuestro widget ObjectListView. Finalmente, realmente llamamos a setBooks() y restablecemos la selección desde que se movió nuestra selección original.
Finalmente
En un principio, este proyecto parecía ya terminado, pero hay al menos un problema con esta implementación y es que no funciona correctamente cuando selecciona varios elementos en el control. Probablemente pueda solucionar esto deshabilitando la selección múltiple en su widget ObjectListView o averiguando la lógica para que funcione con múltiples selecciones. Esto se deja en manos del lector a modo de investigación.
Este artículo esta basado en wxPython: Moving Items in ObjectListView[/vc_column_text][/vc_column][/vc_row]