2015-09-03 3 views
1

У меня есть qtablewidget, и один из его виджетов в каждой строке - qcombobox. Я хотел бы сортировать таблицу в соответствии с содержимым qcomboboxes в каждой строке. Как это сделать? Любая помощь приветствуется.Сортировка qtablewidget от qcombobox currentText

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''' 

ответ

0
  • установить QSignalMapper
  • подключить его к способу сортировки
  • подключить currentTextChanged() -СИГНАЛ из Наримера с signalmapper
  • и установить ItemData клеток с Наримером к currentText() (необходимо, потому что нечего сортировать, если все ячейки содержат только поля со списками)
  • пункт обновленияДетали, если currentText() изменений.

здесь рабочий пример в 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) 
+0

ТНХ много @ a_manthey_67, я постараюсь его :) – paddy

+0

@paddy: см. Мое редактирование в table_sorting_clicked –

+0

thx @ a_manthey_67 Я попробовал отредактированное решение. это дает мне некоторые проблемы просто потому, что ячейка, которая имеет combobox, теперь нуждается в другом btn, поэтому я создаю виджет, который устанавливает горизонтальный макет, который содержит 2 виджета (combobox - это виджет номер 1 в макете) , Я пытаюсь сделать это вписываться в код, но мне не удастся :( using self.cellWidget (i, 1) .layout(). ItemAt (0) .widget(). CurrentText() – paddy