考虑一个QTableWidget和两个按钮“上移”和“下移”。单击“上移”,当前行应上移一行,类似于“下移”。
实现相应的上移和下移功能最简单的方法是什么?

最佳答案

我修改了我的答案,因为它以前没有足够的细节
这个过程包括将按钮连接到一个(或多个)插槽,该插槽将查看当前选择,并通过从视图中取出按钮并将其插入新位置来移动它们。
下面的示例实际使用QTableView+QStandardItemModel。原因是因为QTableWidget更为有限,因为您只能使用小部件中的方法。直接使用模型和选择模型要容易得多。尽管如此,如果您多次使用takeItem()来构建每一行,则可以为QTableWidget重新编写此示例。。。
下面是一个完全有效的示例:

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()将整行作为索引列表删除,然后将该行重新插入到新的行号中。在循环之后,我们使用保存的项查找新索引并再次重新选择它们。

07-26 09:30