2

考虑一个 QTableWidget 和两个按钮“上移”和“下移”。点击上移,当前行应该上移一行,类似于“下移”。

实现相应的上移和下移功能最简单的方法是什么?

4

2 回答 2

10

我设法做到了 only QTableWidget,这是一个完整的例子:

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_())
于 2012-08-13T08:54:45.193 回答
4

我已经修改了我的答案,因为它之前没有足够的细节

该过程涉及将您的按钮连接到一个插槽(或多个插槽),该插槽将查看当前选择,并通过将它们从视图中取出并将它们插入新位置来移动它们。

下面的例子实际上是使用了一个 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()将整行作为索引列表删除,然后将该行重新插入到新的行号中。在那个循环之后,我们使用我们保存的项目来查找新索引并再次重新选择它们。

于 2012-02-06T19:41:21.387 回答