【问题标题】:Sorting qtablewidget by qcombobox currentText通过 qcombobox currentText 对 qtablewidget 进行排序
【发布时间】:2015-09-03 22:42:18
【问题描述】:

我有一个 qtablewidget,每行中的一个单元格小部件是一个 qcombobox。我想根据每行中 qcomboboxes 的内容对表格进行排序。怎么做?非常感谢任何帮助。

self.table = QTableWidget(0,5)
self.table.setSortingEnabled(True)
self.table.horizontalHeader().sortIndicatorChanged.connect(self.table_sorting_clicked)

'''some code here'''

def table_sorting_clicked(self,logicalIndex,order):

'''some code here'''

【问题讨论】:

    标签: python sorting pyside qtablewidget qcombobox


    【解决方案1】:
    • 安装QSignalMapper
    • 连接到排序方法
    • 将组合框的currentTextChanged()-signal 与信号映射器连接
    • 并将带有组合框的单元格的 itemData 设置为currentText()(必须的,因为如果所有单元格都只包含组合框,则无需排序)
    • 如果currentText() 发生变化,则更新 itemData。

    这里是 pyqt5 中的一个工作示例:

    class MyTableWidget(QtWidgets.QTableWidget):
        def __init__(self, parent = None):
            QtWidgets.QTableWidget.__init__(self, parent)
            self.setRowCount(5)
            self.setColumnCount(2)
    
            self.signalMapper = QtCore.QSignalMapper(self)
            self.signalMapper.mapped.connect(self.table_sorting_clicked)
            self.horizontalHeader().sortIndicatorChanged.connect(self.changeSortOrder)
    
            texts = []
            for i in ['A','B','C','D','E','F','G','H','I','J']:
                texts.append(i)
    
            for i in range(0,self.rowCount()):
                combo = QtWidgets.QComboBox()
                combo.addItems(texts)
                combo.setCurrentIndex(i)
                combo.currentTextChanged.connect(self.signalMapper.map)
                self.signalMapper.setMapping(combo, i)
                self.setItem(i,0,QtWidgets.QTableWidgetItem(str(i+1)))
                self.setItem(i,1,QtWidgets.QTableWidgetItem())
                self.setCellWidget(i,1,combo)
                self.item(i,1).setData(0, combo.currentText())
    
            self.setSortingEnabled(True)
            self.sortOrder = 0
    
        def table_sorting_clicked(self, index):
            self.item(index,1).setData(0, self.cellWidget(index,1).currentText())
            self.sortByColumn(1,self.sortOrder)
            # edit 04.09.2015 19:40 
            #this doesn't work correctly if called several times
            # add the following code:
            for i in range(self.rowCount()):
                self.signalMapper.removeMappings(self.cellWidget(i,1))
                self.cellWidget(i,1).currentTextChanged.connect(self.signalMapper.map)
                self.signalMapper.setMapping(self.cellWidget(i,1), i)
    
        def changeSortOrder(self,logicalIndex,order):
            self.sortOrder = order
            self.sortByColumn(logicalIndex,self.sortOrder)
    

    但对于您的目的而言,使用委托可能是更好的选择。在那里您可以将 QListWidget 设置为用户的编辑器/选择器,并且您不需要另外设置项目数据,信号会更简单:

    class MyDelegate(QtWidgets.QStyledItemDelegate):
        def __init__(self, t, parent=None,):
            QtWidgets.QStyledItemDelegate.__init__(self) 
            self.setParent(parent) 
            self.editorTexte = t
    
        def createEditor(self,parent, option, index):
            if index.column() == 1:
                return QtWidgets.QListWidget(parent)
            return QtWidgets.QStyledItemDelegate.createEditor(self,parent, option, index)
    
        def setEditorData(self, editor, index):
            value = str(index.data())
            if index.column() == 1:
                for i, v in enumerate(self.editorTexte):
                    item = QtWidgets.QListWidgetItem(v)
                    editor.addItem(item)
                    if v == value:
                        editor.setCurrentItem(editor.item(i)) 
                x = self.parent().columnViewportPosition(index.column())
                y = self.parent().rowViewportPosition(index.row())
                w = self.parent().columnWidth(index.column())
                h = self.parent().rowHeight(index.row())*5
                editor.setGeometry(x,y,w,h)
            else:
                QtWidgets.QStyledItemDelegate.setEditorData(self, editor, index)
    
        def setModelData(self,editor,model,index):
            if index.column() == 1:
                v = editor.currentItem().text()
            else:
                v = editor.text()
            model.setData(index, v)
    
    class MyTableWidget(QtWidgets.QTableWidget):
        def __init__(self, parent = None):
            QtWidgets.QTableWidget.__init__(self, parent)
            self.setRowCount(5)
            self.setColumnCount(2)
    
            texts = []
            for i in ['A','B','C','D','E','F','G','H','I','J']:
                texts.append(i)
            self.setItemDelegate(MyDelegate(texts, self))
    
            for i in range(0,self.rowCount()):
                self.setItem(i,0,QtWidgets.QTableWidgetItem(str(i+1)))
                self.setItem(i,1,QtWidgets.QTableWidgetItem(texts[i]))
    
            self.setSortingEnabled(True)
            self.sortOrder = 0
            self.sortByColumn(1,self.sortOrder)
            self.horizontalHeader().sortIndicatorChanged.connect(self.changeSortOrder)
    
        def changeSortOrder(self,logicalIndex,order):
            self.sortOrder = order
            self.sortByColumn(logicalIndex,self.sortOrder)  
    

    【讨论】:

    • thx @a_manthey_67 我尝试了您编辑的解决方案。它给我带来了一些麻烦,仅仅是因为具有组合框的单元格现在需要在其中有另一个 btn,所以我正在创建一个小部件来设置包含 2 个小部件的水平布局(组合框是布局中的小部件编号 1) .我试图使它适合代码,但没有得到任何运气:( 使用 self.cellWidget(i,1).layout().itemAt(0).widget().currentText()
    • 它总是给出一个致命错误而没有说明原因
    • 这个按钮是干什么用的?如果更改了一个单元格中的选择,则对表格小部件进行排序。
    • 该按钮用于设置颜色以显示行中第一个单元格的旧状态。与组合框无关,但必须与组合框在相同的布局和单元格中
    • 并且当组合框的索引改变时它不应该排序,只基于已经存在的组合的内容,如果这是有意义的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 2016-02-27
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 2018-10-18
    • 2016-01-26
    相关资源
    最近更新 更多