本文介绍了在 PyQT4 中上下移动行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个 QTableWidget 和两个按钮向上移动"和向下移动".单击向上移动,当前行应向上移动一行,类似于向下移动".

Consider a QTableWidget and two buttons "move up" and "move down". Clicking on move up, the current row should move up one row, analogously for "move down".

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

What's the easiest way to implement the corresponding move up and move down functions?

推荐答案

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

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

The process involves connecting your buttons to a slot (or slots) that will look at the current selection, and move them by taking them from the view, and inserting them into new locations.

下面的例子实际上是使用了一个 QTableView + QStandardItemModel.原因是因为 QTableWidget 受到更多限制,因为您只能使用来自小部件的方法.能够直接使用模型和选择模型要容易得多.虽然,如果您多次使用 takeItem() 来构建每一行,则可以为 QTableWidget 重新编写此示例...

The following example is actually using a QTableView + QStandardItemModel. The reason is because QTableWidget is much more limited since you can only use methods from the widget. Its a lot easier to be able to work directly with the model and selection model. Although, it is possible to rework this example for a QTableWidget if you use takeItem() multiple times to build up each row...

这是一个完整的示例:

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 的数据.

The init is simple and just sets up the table, model, and buttons. We connect both buttons to the same method using functools.partial, which is really convenient for wrapping up the same function call with different args. Then the table is just filled with 20x6 data.

当一个按钮被点击时,我们确保他们选择了行.对于每个选定的行,我们解析它的项目(以便在移动后重新选择),并通过添加或减去一个来确定新的行号.我们还确保它在有效的移动范围内,否则我们跳过它.最后,我们调用 takeRow() 将整行作为索引列表删除,然后将该行插入到新的行号中.在该循环之后,我们使用我们保存的项目来查找新索引并再次重新选择它们.

When a button is clicked, we make sure they have selected rows. For each selected row, we resolve its item (for re-selection later once it has moved), and determine the new row number by either adding or subtracting one. We also make sure its within the valid range to move, otherwise we skip it. Finally, we call takeRow() to remove the entire row as a list of indexes, and then insert that row back into the new row number. After that loop, we use the items we saved to look up the new indexes and reselect them again.

这篇关于在 PyQT4 中上下移动行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 19:34