2012-12-28 8 views
7

Sto usando QTableView per visualizzare i dati recuperati da QtSql.QSqlQueryCome creare filtri per QTableView in PyQt

voglio sapere come posso creare filtri per esso come in Excel.

enter image description here

Nell'immagine qui sopra ho bisogno di ottenere i filtri per Tutti heders (Sh_Code, SH_Seq, Stage) I filtri avranno valori unici di quella colonna su cui possiamo filtrare.

risultato richiesto

Ho bisogno l'intestazione vista da tavolo con un set che elenca tutti i valori univoci in quella colonna, proprio come in excel qui sotto. Non è necessario il filtro Top, Standard ... come mostrato nell'immagine. solo "All" e le "voci colonna" unici

enter image description here

Questo è dalla mia applicazione .NET bisogno, caricato per maggiore chiarezza

enter image description here

risposta

15

Ecco un esempio di filtraggio in PyQt utilizzando QSortFilterProxyModel, QStandardItemModel e QTableView, può essere facilmente adattato ad altre viste e modelli:

#!/usr/bin/env python 
#-*- coding:utf-8 -*- 

from PyQt4 import QtCore, QtGui 

class myWindow(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(myWindow, self).__init__(parent) 
     self.centralwidget = QtGui.QWidget(self) 
     self.lineEdit  = QtGui.QLineEdit(self.centralwidget) 
     self.view   = QtGui.QTableView(self.centralwidget) 
     self.comboBox  = QtGui.QComboBox(self.centralwidget) 
     self.label   = QtGui.QLabel(self.centralwidget) 

     self.gridLayout = QtGui.QGridLayout(self.centralwidget) 
     self.gridLayout.addWidget(self.lineEdit, 0, 1, 1, 1) 
     self.gridLayout.addWidget(self.view, 1, 0, 1, 3) 
     self.gridLayout.addWidget(self.comboBox, 0, 2, 1, 1) 
     self.gridLayout.addWidget(self.label, 0, 0, 1, 1) 

     self.setCentralWidget(self.centralwidget) 
     self.label.setText("Regex Filter") 

     self.model = QtGui.QStandardItemModel(self) 

     for rowName in range(3) * 5: 
      self.model.invisibleRootItem().appendRow(
       [ QtGui.QStandardItem("row {0} col {1}".format(rowName, column))  
        for column in range(3) 
        ] 
       ) 

     self.proxy = QtGui.QSortFilterProxyModel(self) 
     self.proxy.setSourceModel(self.model) 

     self.view.setModel(self.proxy) 
     self.comboBox.addItems(["Column {0}".format(x) for x in range(self.model.columnCount())]) 

     self.lineEdit.textChanged.connect(self.on_lineEdit_textChanged) 
     self.comboBox.currentIndexChanged.connect(self.on_comboBox_currentIndexChanged) 

     self.horizontalHeader = self.view.horizontalHeader() 
     self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked) 

    @QtCore.pyqtSlot(int) 
    def on_view_horizontalHeader_sectionClicked(self, logicalIndex): 
     self.logicalIndex = logicalIndex 
     self.menuValues  = QtGui.QMenu(self) 
     self.signalMapper = QtCore.QSignalMapper(self) 

     self.comboBox.blockSignals(True) 
     self.comboBox.setCurrentIndex(self.logicalIndex) 
     self.comboBox.blockSignals(True) 

     valuesUnique = [ self.model.item(row, self.logicalIndex).text() 
          for row in range(self.model.rowCount()) 
          ] 

     actionAll = QtGui.QAction("All", self) 
     actionAll.triggered.connect(self.on_actionAll_triggered) 
     self.menuValues.addAction(actionAll) 
     self.menuValues.addSeparator() 

     for actionNumber, actionName in enumerate(sorted(list(set(valuesUnique)))):    
      action = QtGui.QAction(actionName, self) 
      self.signalMapper.setMapping(action, actionNumber) 
      action.triggered.connect(self.signalMapper.map) 
      self.menuValues.addAction(action) 

     self.signalMapper.mapped.connect(self.on_signalMapper_mapped) 

     headerPos = self.view.mapToGlobal(self.horizontalHeader.pos())   

     posY = headerPos.y() + self.horizontalHeader.height() 
     posX = headerPos.x() + self.horizontalHeader.sectionPosition(self.logicalIndex) 

     self.menuValues.exec_(QtCore.QPoint(posX, posY)) 

    @QtCore.pyqtSlot() 
    def on_actionAll_triggered(self): 
     filterColumn = self.logicalIndex 
     filterString = QtCore.QRegExp( "", 
             QtCore.Qt.CaseInsensitive, 
             QtCore.QRegExp.RegExp 
             ) 

     self.proxy.setFilterRegExp(filterString) 
     self.proxy.setFilterKeyColumn(filterColumn) 

    @QtCore.pyqtSlot(int) 
    def on_signalMapper_mapped(self, i): 
     stringAction = self.signalMapper.mapping(i).text() 
     filterColumn = self.logicalIndex 
     filterString = QtCore.QRegExp( stringAction, 
             QtCore.Qt.CaseSensitive, 
             QtCore.QRegExp.FixedString 
             ) 

     self.proxy.setFilterRegExp(filterString) 
     self.proxy.setFilterKeyColumn(filterColumn) 

    @QtCore.pyqtSlot(str) 
    def on_lineEdit_textChanged(self, text): 
     search = QtCore.QRegExp( text, 
            QtCore.Qt.CaseInsensitive, 
            QtCore.QRegExp.RegExp 
            ) 

     self.proxy.setFilterRegExp(search) 

    @QtCore.pyqtSlot(int) 
    def on_comboBox_currentIndexChanged(self, index): 
     self.proxy.setFilterKeyColumn(index) 


if __name__ == "__main__": 
    import sys 

    app = QtGui.QApplication(sys.argv) 
    main = myWindow() 
    main.show() 
    main.resize(400, 600) 
    sys.exit(app.exec_()) 

Per ottenere i risultati richiesti, viene lanciato un menu popup facendo clic sull'intestazione e popolato con i valori univoci per quella colonna. Una volta selezionato un elemento nel menu popup, il valore viene passato a self.proxy.setFilterRegExp(filterString) e la colonna a self.proxy.setFilterKeyColumn(filterValue).

image

+0

sua non ricevendo alcuna cosa filtrato quando si digita "riga 0 col 0" nella casella di filtro. ho aggiunto dichiarazioni di stampa in 'on_lineEdit_textChanged'' on_comboBox_currentIndexChanged' ma non vengono mai eseguite. Sto lavorando su Python 2.6.4 – Rao

+0

@PBLNarasimhaRao Hai dimenticato di connettere gli slot! Ho aggiornato [il codice] (http://stackoverflow.com/a/14075797/1006989), dovrebbe funzionare ora –

+0

ha funzionato collegando i segnali 'self.comboBox.currentIndexChanged.connect (self.on_comboBox_currentIndexChanged)' e ' self.lineEdit.textChanged.connect (self.on_lineEdit_textChanged) 'Ma ho bisogno di un filtro per essere visualizzato sulle intestazioni delle colonne, da dove posso selezionarlo (ad esempio, come in Excel). ho aggiornato la domanda con uno snapshot excel che è richiesto. – Rao