python pyqt pyqt4 qtablewidget

python - Mueve la fila hacia arriba y hacia abajo en PyQT4



qtablewidgetitem pyqt (2)

Considere un QTableWidget y dos botones "mover hacia arriba" y "mover hacia abajo". Al hacer clic en mover hacia arriba, la fila actual debe avanzar una fila, análogamente para "mover hacia abajo".

¿Cuál es la forma más fácil de implementar las funciones correspondientes de subir y bajar?


QTableWidget hacerlo usando QTableWidget , aquí hay un ejemplo completo:

import sys from PyQt4 import QtCore from PyQt4 import QtGui class mtable(QtGui.QMainWindow): def __init__(self, parent=None): QtGui.QWidget.__init__(self, parent) self.move_up = QtGui.QAction("Move_Up", self) self.connect(self.move_up, QtCore.SIGNAL(''triggered()''), self.moveUp) self.move_down = QtGui.QAction("Move_Down",self) self.connect(self.move_down, QtCore.SIGNAL(''triggered()''), self.moveDown) self.toolbar = self.addToolBar(''Toolbar'') self.toolbar.addAction(self.move_up) self.toolbar.addAction(self.move_down) ##Init Table self.table = QtGui.QTableWidget(4,3) for i in range(0,4): for j in range(0,4): self.table.setItem(i,j,QtGui.QTableWidgetItem("a_"+str(i)+str(j))) self.setCentralWidget(self.table) def moveDown(self): row = self.table.currentRow() column = self.table.currentColumn(); if row < self.table.rowCount()-1: self.table.insertRow(row+2) for i in range(self.table.columnCount()): self.table.setItem(row+2,i,self.table.takeItem(row,i)) self.table.setCurrentCell(row+2,column) self.table.removeRow(row) def moveUp(self): row = self.table.currentRow() column = self.table.currentColumn(); if row > 0: self.table.insertRow(row-1) for i in range(self.table.columnCount()): self.table.setItem(row-1,i,self.table.takeItem(row+1,i)) self.table.setCurrentCell(row-1,column) self.table.removeRow(row+1) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) tb = mtable() tb.show() sys.exit(app.exec_())


He revisado mi respuesta porque no tenía suficiente detalle previamente

El proceso implica conectar los botones a una ranura (o ranuras) que observará la selección actual y moverlos tomándolos de la vista e insertándolos en nuevas ubicaciones.

El siguiente ejemplo está usando un QTableView + QStandardItemModel. La razón es porque QTableWidget es mucho más limitado ya que solo puedes usar métodos del widget. Es mucho más fácil poder trabajar directamente con el modelo y el modelo de selección. Aunque, es posible volver a trabajar este ejemplo para un QTableWidget si usa takeItem() varias veces para crear cada fila ...

Aquí hay un ejemplo completamente funcional:

from PyQt4 import QtCore, QtGui from functools import partial class Dialog(QtGui.QDialog): DOWN = 1 UP = -1 def __init__(self, parent=None): super(Dialog, self).__init__(parent) self.resize(800,600) self.table = QtGui.QTableView(self) self.table.setSelectionBehavior(self.table.SelectRows) self.model = QtGui.QStandardItemModel(20, 6, self) self.table.setModel(self.model) self.upBtn = QtGui.QPushButton(''Up'', self) self.downBtn = QtGui.QPushButton(''Down'', self) self.mainLayout = QtGui.QVBoxLayout(self) self.mainLayout.addWidget(self.table) self.buttonLayout = QtGui.QHBoxLayout() self.buttonLayout.addWidget(self.upBtn) self.buttonLayout.addWidget(self.downBtn) self.mainLayout.addLayout(self.buttonLayout) self.upBtn.clicked.connect(partial(self.moveCurrentRow, self.UP)) self.downBtn.clicked.connect(partial(self.moveCurrentRow, self.DOWN)) self._initTable() def _initTable(self): for row in xrange(self.model.rowCount()): for col in xrange(self.model.columnCount()): item = QtGui.QStandardItem(''%d_%d'' % (row+1, col+1)) self.model.setItem(row, col, item) def moveCurrentRow(self, direction=DOWN): if direction not in (self.DOWN, self.UP): return model = self.model selModel = self.table.selectionModel() selected = selModel.selectedRows() if not selected: return items = [] indexes = sorted(selected, key=lambda x: x.row(), reverse=(direction==self.DOWN)) for idx in indexes: items.append(model.itemFromIndex(idx)) rowNum = idx.row() newRow = rowNum+direction if not (0 <= newRow < model.rowCount()): continue rowItems = model.takeRow(rowNum) model.insertRow(newRow, rowItems) selModel.clear() for item in items: selModel.select(item.index(), selModel.Select|selModel.Rows) if __name__ == "__main__": app = QtGui.QApplication([]) d = Dialog() d.show() d.raise_() app.exec_()

El init es simple y solo configura la tabla, el modelo y los botones. Conectamos ambos botones al mismo método utilizando functools.partial , lo cual es muy conveniente para functools.partial la misma llamada de función con diferentes argumentos. Luego, la tabla está llena de datos de 20x6.

Cuando se hace clic en un botón, nos aseguramos de que tengan filas seleccionadas. Para cada fila seleccionada, resolvemos su ítem (para volver a seleccionarlo más adelante una vez que se ha movido) y determinamos el nuevo número de fila agregando o restando uno. También nos aseguramos de que esté dentro del rango válido para moverse, de lo contrario, nos salteamos. Finalmente, llamamos a takeRow() para eliminar toda la fila como una lista de índices, y luego insertamos esa fila nuevamente en el nuevo número de fila. Después de ese ciclo, usamos los elementos que guardamos para buscar los nuevos índices y volver a seleccionarlos.