Я пересмотрел свой ответ, потому что ранее у него не было достаточно деталей
Процесс включает в себя подключение кнопок к слоту (или слотам), который будет смотреть на текущий выбор, ипереместите их, взяв их из вида и вставив в новые местоположения.
В следующем примере фактически используется QTableView + QStandardItemModel.Причина в том, что QTableWidget намного более ограничен, поскольку вы можете использовать только методы из виджета.Намного проще иметь возможность работать непосредственно с моделью и моделью выбора.Хотя, возможно, переделать этот пример для QTableWidget, если вы используете takeItem()
несколько раз для построения каждой строки ...
Вот полностью рабочий пример:
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_()
Программа init проста и устанавливает таблицу, модель и кнопки.Мы подключаем обе кнопки к одному и тому же методу, используя functools.partial
, что действительно удобно для переноса одного и того же вызова функции разными аргументами.Затем таблица просто заполняется данными размером 20x6.
При нажатии кнопки мы проверяем, что они выбрали строки.Для каждой выбранной строки мы разрешаем ее элемент (для повторного выбора позже после его перемещения) и определяем новый номер строки, добавляя или вычитая его.Мы также проверяем, чтобы он находился в допустимом диапазоне, иначе мы его пропускаем.Наконец, мы вызываем takeRow()
, чтобы удалить всю строку в виде списка индексов, а затем вставляем эту строку обратно в новый номер строки.После этого цикла мы используем сохраненные элементы для поиска новых индексов и повторного их выбора.