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